SORU
19 EYLÜL 2008, Cuma


Sıkı yumuşatma kuralı nedir?

common undefined behavior in C, ruhlar sıkı yumuşatma kuralı anlattım daha aydınlanmış soruyor.< / ^ br . Neden bahsediyor bunlar?

CEVAP
19 EYLÜL 2008, Cuma


Tipik bir durumla karşılaştığınız strict aliasing sorunları olduğunda kaplayan bir yapı (gibi bir aygıt/ağ msg) üzerine bir tampon sözü boyutta sistemi (gibi bir işaretçi uint32_ts uint16_ts). Böyle bir tampon üzerine bir yapı kaplama veya işaretçi döküm yoluyla böyle bir yapı üzerine bir tampon zaman kolayca strict aliasing kuralları ihlal edebilirsiniz.

Eğer bir şey için bir mesaj göndermek istiyorum eğer kurulum bu tür, İki uyumsuz işaretçiler bellek aynı yığın işaret etmek istiyorum. Ben safça kod şöyle bir şey olabilir:

struct Msg
{
   unsigned int a;
   unsigned int b;
};

void SendWord(uint32_t*);

int main()
{
   // Get a 32-bit buffer from the system
   uint32_t* buff = malloc(sizeof(Msg));

   // Alias that buffer through message
   Msg* msg = (Msg*)(buff);

   // Send a bunch of messages    
   for (int i =0; i < 10;   i)
   {
      msg->a = i;
      msg->b = i 1;
      SendWord(buff[0] );
      SendWord(buff[1] );   
   }
}

Sıkı yumuşatma kuralı bu Kur yasadışı yapar: incompatible type tanımsız davranış. başka bir takma ad bir işaretçi kaldırma Ne yazık ki, hala bu şekilde, belki bazı uyarılar, güzel, derleme kodunu çalıştırdığınızda, garip, beklenmeyen bir davranış için sadece kodu.

*(gcc aliasing uyarılar, bize dostça bir uyarı vermek için kendi yeteneği here here çok tutarsız görünüyor)

Bu davranışı tanımlı değil, sıkı yumuşatma kuralı derleyici aldığı şey düşünmek zorundayız. Temel olarak, bu kural ile, talimatları buff döngünün her çalışma içeriğini yenilemek için ekleme hakkında düşünmek zorunda değil. Bunun yerine, ne zaman optimize, bazı rahatsız edici zorlanmayan varsayımlar hakkında aliasing, ihmal bu talimatları, yük buff[0] buff[1] Daha önce bir kez döngü çalıştırmak ve hızlandırmak vücudun döngü. Strict aliasing tanıtıldı önce, derleyici buff içeriği herkes tarafından herhangi bir yerden herhangi bir zamanda değiştirebilir paranoya bir devlet içinde yaşamak zorunda kaldı. Ekstra bir performans kenar elde etmek için, ve çoğu insan türü-cinas işaretçileri yok farz edelim, sıkı aliasing ' şartı getirildi.

Bunun yerine varsa aklında ise yapmacık olduğunu düşünüyorsanız, bu bile başka bir işlev için bir tampon yolunuz düşerse olabileceğini sana gönderme yapıyor, devam et.

 void SendMessage(uint32_t* buff, size_t size32)
 {
    for (int i = 0; i < size32;   i) 
    {
       SendWord(buff[i]);
    }
 }

Ve bu kullanışlı işlevi yararlanmak için bizim önceki döngü yeniden yazdı

   for (int i =0; i < 10;   i)
   {
      msg->a = i;
      msg->b = i 1;
      SendMessage(buff, 2);
   }

Derleyici olabilir veya SendMessage içi denemek için yeterince akıllı olmayabilir ve olabilir veya yük veya buff tekrar yüklemek için karar verebilir. Eğer SendMessage ayrı olarak derlenmiş başka bir API bir parçası ise, muhtemelen yük buff içeriği için talimatları vardır. Sonra tekrar, belki C ve bu derleyici satır içi olabilir düşünen bir şablon Başlığı sadece uygulamasıdır. Ya da belki sadece senin yazdığın bir şey değil .c kendi rahatınız için dosya. Zaten tanımsız davranış hala doğmak olabilir. Kaputun altında ne olup bittiğini biliyoruz bile, hala iyi tanımlanmış davranış garantili şekilde kural ihlali var. Yani bizim kelime ayrılmış arabellek götüren bir işlevi sararak sadece mutlaka yardımcı olmuyor.

Bu nasıl bir çözüm bulabilirim?

  • Bir sendika kullanın. Çoğu derleyici strict aliasing şikayet olmadan bu desteği. Bu C99 izin verilir ve açıkça C11 verdi.
    union {
        Msg msg;
        unsigned int asBuffer[sizeof(Msg)/sizeof(unsigned int)];
    };
  • Derleyici (23* *gcc)) sıkı aliasing devre dışı bırakabilirsiniz

  • Sistem kelimesi yerine aliasing char* kullanabilirsiniz. Kurallar char* için bir istisna (signed char unsigned char dahil) izin verir. Her zaman char* diğer türleri diğer adları olduğu kabul edilmektedir. Bu başka bir şekilde çalışmaz ancak: yapı karakter bir tampon takma bu varsayım yok.

Dikkat acemi

Bu birbiri üzerine iki tür kaplayan tek bir potansiyel mayın tarlası gibi. Ayrıca packing structs doğru ile uyum sorunları ile başa çıkmak için nasıl endianness, word alignment, hakkında bilgi edinmek gerekir.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • 30GB

    30GB

    14 AĞUSTOS 2006
  • Apple&Tech Reviews & Giveaways

    Apple&Tech R

    12 Temmuz 2008
  • jesiel santos

    jesiel santo

    15 Ocak 2009