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
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_t
s uint16_t
s). 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. Kurallarchar*
için bir istisna (signed char
unsigned char
dahil) izin verir. Her zamanchar*
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.
nedir &; sıkı modu " " ve nasıl k...
&Quot;sıkı" kullanın; JavaScript, ...
gevşek bağlantı ve sıkı kavrama arasın...
MySQL Sayılı için uygun bir adlandırma...
Üç Kuralı nedir?...