C ile çakışan nesnelerin semantiği nedir?


25

Aşağıdaki yapıyı düşünün:

struct s {
  int a, b;
};

Tipik olarak 1 , bu yapı 8 ebatına ve 4 hizalamasına sahip olacaktır.

Ya iki struct snesne yaratırsak (daha kesin olarak, tahsis edilen depoya bu tür iki nesneyi yazarız), ikinci nesne birinciyle çakışırsa?

char *storage = malloc(3 * sizeof(struct s));
struct s *o1 = (struct s *)storage; // offset 0
struct s *o2 = (struct s *)(storage + alignof(struct s)); // offset 4

// now, o2 points half way into o1
*o1 = (struct s){1, 2};
*o2 = (struct s){3, 4};

printf("o2.a=%d\n", o2->a);
printf("o2.b=%d\n", o2->b);
printf("o1.a=%d\n", o1->a);
printf("o1.b=%d\n", o1->b);

Bu program hakkında tanımlanmamış bir davranış var mı? Öyleyse, nerede tanımsız hale geliyor? UB değilse, aşağıdakilerin her zaman yazdırılması garanti edilir:

o2.a=3
o2.b=4
o1.a=1
o1.b=3

Özellikle, örtüştüğü nesneye o1ne zaman o2, hangi örtüşmeyle yazıldığını bilmek istiyorum . Açılmamış parçaya ( o1->a) erişmeye hala izin var mı ? Hızlandırılmış bölüme erişim, erişim ile o1->baynı o2->amıdır?

Etkili tip burada nasıl uygulanır? Kurallar, son mağaza ile aynı konuma işaret eden çakışmayan nesneler ve işaretçiler hakkında konuşurken yeterince açıktır, ancak nesnelerin veya üst üste binen nesnelerin etkili türü hakkında konuşmaya başladığınızda, bu daha az açıktır.

İkinci yazı farklı tipteyse bir şey değişebilir mi? Üyeler söylendi intve shortiki ints yerine ?

Burada onunla oynamak istiyorsanız bir vaftiz babası .


1 Bu yanıt, durumun böyle olmadığı platformlar için de geçerlidir: örneğin, bazılarının boyutu 4 ve hizalama 2 olabilir. Boyut ve hizalamanın aynı olduğu bir platformda, bu soru hizalanmış, çakışan nesneler olacağı için geçerli olmaz imkansız ol, ama böyle bir platform olup olmadığından emin değilim.


2
Eminim UB, ama bir dil avukatının bölüm ve ayet sağlamasına izin vereceğim.
Barmar

Eski Cray vektör sistemlerindeki C derleyicisinin, ILP64 modeli ve zorla 64 bit hizalama (adresler 64 bit sözcükler - bayt adresleme yok) ile hizalamayı ve boyutu aynı olmaya zorladığını düşünüyorum. Tabii ki bu diğer birçok problem yarattı ....
John D McCalpin

Yanıtlar:


15

Temelde bu standarttaki tüm gri alandır; katı takma adlandırma kuralı temel durumları belirtir ve okuyucuyu (ve derleyici satıcılarını) ayrıntıları doldurması için bırakır.

Daha iyi bir kural yazma çabaları oldu, ancak şimdiye kadar herhangi bir normatif metinle sonuçlanmadılar ve bunun durumunun C2x için ne olduğundan emin değilim.

Önceki sorunuza verdiğim yanıtta da belirtildiği gibi, en yaygın yorum , daha sonra başvurmaya devam etsek de , p->qaraçların (*p).qve etkili türün hepsine *puygulanır .q.

Bu yorum altında , konumun etkili türü olmadığından (bir kısmının üzerine yazıldığı için) printf("o1.a=%d\n", o1->a);tanımlanmamış davranışa neden olur .*o1s

Bu yorumun mantığı aşağıdaki gibi bir işlevde görülebilir:

void f(s* s1, s* s2)
{
    s2->a = 5;
    s1->b = 6;
    printf("%d\n", s2->a);
}

Bu yorum ile son satır optimize edilebilir puts("5");, fakat onsuz, derleyici fonksiyon çağrısının yapılmış olabileceğini düşünmelidir f(o1, o2);ve bu nedenle katı örtüşme kuralı tarafından sağlanan tüm faydaları kaybedebilir.

Benzer bir argüman, her ikisi intde farklı ofsette bir üyesi olan iki ilişkisiz yapı tipi için geçerlidir .


1
Derleyici ile f(s* s1, s* s2), olmadan restrict, derleyici farklı göstergeler üstlenemez s1ve kabul edemez s2. Ben düşünüyorum tekrar etmeden, restricthatta kısmen örtüşme yok kabul edemeyiz. IAC, OP'nin endişesinin f()analoji tarafından iyi bir şekilde demode olduğunu görmüyorum . İyi şanslar kargaşa. İlk yarı için UV.
chux - Monica'yı geri yükle

@ chux-ReinstateMonica kısıtlama olmaksızın s1 == s2izin verilir, ancak kısmi çakışma olmaz. (Kod örneğimdeki optimizasyon yine de yapılabilir s1 == s2)
MM

@ chux-ReinstateMonica da aynı sorunu sadece intyapılar (ve bir sistem _Alignof(int) < sizeof(int)) yerine düşünebilirsiniz .
MM

3
C2x için etkili tip ile ilgili bu tür bir sorunun durumu oldukça açıktır ve çalışma grubunda tartışmaya açıktır. Denkliğini iddia dikkatli olsa olun p->qve (*p).q. Bu, belirttiğiniz gibi tür yorumlaması için doğru olabilir, ancak operasyonel bir bakış açısından doğru değildir. Bir üyeye erişimin diğer üyelerin erişimini ima etmediği aynı yapıya eşzamanlı erişim için önemlidir.
Jens Gustedt

Katı takma adlandırma kuralı erişim ile ilgilidir . Sol taraftaki sentezleme E1.E2ifade Bütün (ortalama erişim gerçekleştirmez E1ise. Onun alt ifadelerin bazıları erişimi yürütebilir. Ekspresyonunu Ie E1olan (*p)değerlendirirken sonra işaretçi değeri, okuma perişimi, ancak değerlendirilmesi *pveya (*p)gerçekleştirmez Giriş). Erişim olmadığı durumlarda katı takma adlandırma kuralı uygulanmaz.
Language Lawyer
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.