SORU
8 EKİM 2012, PAZARTESİ


Bu derleyici optimizasyonu bir hata, ya da tanımsız bir davranıştır?

Kod bu parça açıklayamam sinir bozucu bir hata var:

unsigned char bitmap[K_BITMAP_SIZE] = {0} ;
SetBit(bitmap, K_18); // Sets the bit #18 to 1

for(size_t i = 0; i < K_END;   i)
{
    if(TestBit(bitmap, i)) // true for 18
    {
        size_t i2 = getData(i); // for 18, will return 15
        SetBit(bitmap, i2); // BUG: IS SUPPOSED TO set the bit #15 to 1
    }
}
  1. Visual C 2010 tarihinde olur
  2. 32-bit ve 64-bit hem de inşa olur
  3. Sürüm oluşturur ("Hız (/O2)" olarak ayarlayın. yalnızca en üst düzeye çıkarmak olur
  4. Sadece Serbest "Boyutu (/O1)" olarak ayarlayın . en Aza indirmek ile inşa olmaz
  5. 5 ** getData fonksiyonu (varsayılan olarak, VC 2008 işlev satır içi değil, VC 2010 yaparken) sadece Visual C 2008 olur
  6. Döngü içinde kod aşağıda, muhtemelen büyük satır içi uygulaması nedeniyle verilen parça üzerinde olur
  7. Biz döngü kaldırmak ve doğrudan ilginç değeri (18) ayarlamak olmaz

Bonus bilgi:

1 - BenJ C, 2012, anlamı bu derleyici bir hata olabilir bu sorun, Visual görünmüyor yorumladı

Eğer Test//Set unsigned char alçı eklersek 2 - ResetBit fonksiyonları, hata da kaybolur

size_t TestBit(const unsigned char * bits, size_t pos) { return (((bits)[(pos) >> 3]) &   (1 << (unsigned char)((pos) & 7))) ; }
size_t SetBit(unsigned char * bits, size_t pos)        { return (((bits)[(pos) >> 3]) |=  (1 << (unsigned char)((pos) & 7))) ; }
size_t ResetBit(unsigned char * bits, size_t pos)      { return (((bits)[(pos) >> 3]) &= ~(1 << (unsigned char)((pos) & 7))) ; }

Soru:

Bu hata kodu tanımsız davranış dayanır, ya da orada VC 2010 derleyici bazı böcek için olur mu?

Aşağıdaki kaynak-kendi kendine yeterli, ve en sevdiğiniz derleyici gibi derlenmiş olabilir:

#include <iostream>


const size_t K_UNKNOWN              = (-1) ;
const size_t K_START                = (0) ;
const size_t K_12                   = (K_START   12) ;
const size_t K_13                   = (K_START   13) ;
const size_t K_15                   = (K_START   15) ;
const size_t K_18                   = (K_START   18) ;
const size_t K_26                   = (K_START   26) ;
const size_t K_27                   = (K_START   27) ;
const size_t K_107                  = (K_START   107) ;
const size_t K_128                  = (K_START   128) ;
const size_t K_END                  = (K_START   208) ;
const size_t K_BITMAP_SIZE          = ((K_END/8)   1) ;


size_t TestBit(const unsigned char * bits, size_t pos) { return (((bits)[(pos) >> 3]) &   (1 << ((pos) & 7))) ; }
size_t SetBit(unsigned char * bits, size_t pos)        { return (((bits)[(pos) >> 3]) |=  (1 << ((pos) & 7))) ; }
size_t ResetBit(unsigned char * bits, size_t pos)      { return (((bits)[(pos) >> 3]) &= ~(1 << ((pos) & 7))) ; }


size_t getData(size_t p_value)
{
    size_t value = K_UNKNOWN;

    switch(p_value)
    {
        case K_13:      value = K_12;        break;
        case K_18:      value = K_15;        break;
        case K_107:     value = K_15;        break;
        case K_27:      value = K_26;        break;
        case K_128:     value = K_12;        break;
        default:        value = p_value;     break;
    }

    return value;
}


void testBug(const unsigned char * p_bitmap)
{
    const size_t byte = p_bitmap[1] ;
    const size_t bit  = 1 << 7 ;
    const size_t value = byte & bit ;

    if(value == 0)
    {
        std::cout << "ERROR : The bit 15 should NOT be 0" << std::endl ;
    }
    else
    {
        std::cout << "Ok : The bit 15 is 1" << std::endl ;
    }
}


int main(int argc, char * argv[])
{
    unsigned char bitmap[K_BITMAP_SIZE] = {0} ;
    SetBit(bitmap, K_18);

    for(size_t i = 0; i < K_END;   i)
    {
        if(TestBit(bitmap, i))
        {
            size_t i2 = getData(i);
            SetBit(bitmap, i2);
        }
    }

    testBug(bitmap) ;

    return 0;
}

Bazı arka plan bilgileri: Başlangıçta:

  1. Test//Set fonksiyonları makrolar vardı ResetBit.
  2. sabitleri tanımlar
  3. endeksleri long int da (Windows 32-bit, aynı boy var)

Gerekirse, (her iki yapılandırmaları için oluşturulan çevirici örneğin, g sorunun üstesinden nasıl update), en kısa sürede bir kaç bilgi daha ekleyeyim.

CEVAP
8 EKİM 2012, PAZARTESİ


Bu kod iyileştirici bir hata değildir. Hem bu inlines getData() ve SetBit(). Kombinasyonu ölümcül görünüyor, 1 < değerini izini kaybeder;< ((pos) & 7) ve her zaman sıfır üretir.

Bu hata VS2012 oluşmaz. Geçici bir çözüm işlevlerinden biri inlined almak için değil zorlamak için. Kodu verilen, muhtemelen getData için bunu yapmak istiyorum():

__declspec(noinline)
size_t getData(size_t p_value)
{ 
    // etc..
}

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • bmarian22

    bmarian22

    22 Aralık 2007
  • PlugResearch

    PlugResearch

    22 Mart 2006
  • trickycharms

    trickycharms

    6 Aralık 2013