SORU
19 Aralık 2011, PAZARTESİ


Gcc's ____özniteliği((paketlenmiş)) / #pragma pack güvensiz?

C derleyici irade ortaya koymak üyelerinin bir yapı sırayı olduklarını ilan etmiş, Olası doldurma baytları eklenen üyeler arasında, ya sonra son üyesi, emin olmak için her üye düzgün hizalanmış.

gcc sağlar derleyici Ekle doldurma söyler hangi dil uzatma, __attribute__(packed),, yapı üyeleri yanlış hizalanmış olmasını sağlar. Eğer sistem normal int tüm nesneler 4 baytlık hizalama gerektiriyorsa, örneğin, `__attribute__(packed) int yapı üyeleri tek uzaklıklardan tahsis edilmesine neden olabilir.

Gcc belgelere alıntı:

`Özniteliği değişken veya yapı alanını belirtir paketlenmiş mümkün olan en küçük bir uyum var. biri değişken,byte gerekmektedir eğer daha büyük bir değer belirtin sürece ve bir alan için bir bit, `uyumlu' özniteliği.

Açıkçası bu uzatma kullanın derleyici (bazı platformlarda kod bayt bir zamanda yanlış bir üye oluşturmalıdır olarak daha küçük veri gereksinimleri ama yavaş kod neden olabilir.

Ama bu güvensiz olduğu herhangi bir durum var mı? Derleyici her zaman daha yavaş olsa da) kod dolu yapılar bu hizadan üyeleri erişmek için doğru oluşturur mu? Hatta her durumda yapmak mümkün müdür?

CEVAP
19 Aralık 2011, PAZARTESİ


(Evet, kendi soruma cevap veriyorum.)

Evet, __attribute__((packed)) bazı sistemlerde potansiyel olarak güvenli değildir. Bu belirti muhtemelen sorun daha sinsi yapan 86, görünmez; 86 sistemleri test sorunu açıklamaz. (86, yanlış hizalanmış erişir işlediğinden donanım; eğer başvuru int* işaretçi işaret eden garip bir adres olacak biraz daha yavaş olsaydı, bunu düzgün bir şekilde yapıldı, ama alacaksın doğru sonucu.)

Diğer bazı sistemlerde, SPARC gibi int yanlış hizalanmış bir nesneye erişmeye çalışan otobüs bir hata, programın çökmesini neden olur.

Ayrıca yanlış bir erişim sessizce adresini düşük sipariş bit, bellek yanlış parça erişmek için neden yok sayar nerede sistemler var.

Aşağıdaki programı deneyin:

#include <stdio.h>
#include <stddef.h>
int main(void)
{
    struct foo {
        char c;
        int x;
    } __attribute__((packed));
    struct foo arr[2] = { { 'a', 10 }, {'b', 20 } };
    int *p0 = &arr[0].x;
    int *p1 = &arr[1].x;
    printf("sizeof(struct foo)      = %d\n", (int)sizeof(struct foo));
    printf("offsetof(struct foo, c) = %d\n", (int)offsetof(struct foo, c));
    printf("offsetof(struct foo, x) = %d\n", (int)offsetof(struct foo, x));
    printf("arr[0].x = %d\n", arr[0].x);
    printf("arr[1].x = %d\n", arr[1].x);
    printf("p0 = %p\n", (void*)p0);
    printf("p1 = %p\n", (void*)p1);
    printf("*p0 = %d\n", *p0);
    printf("*p1 = %d\n", *p1);
    return 0;
}

Gcc ile 86 Ubuntu 4.5.2, aşağıdaki çıktıyı üretir:

sizeof(struct foo)      = 5
offsetof(struct foo, c) = 0
offsetof(struct foo, x) = 1
arr[0].x = 10
arr[1].x = 20
p0 = 0xbffc104f
p1 = 0xbffc1054
*p0 = 10
*p1 = 20

Gcc ile SPARC Solaris 9 4.5.1, aşağıdaki üretir:

sizeof(struct foo)      = 5
offsetof(struct foo, c) = 0
offsetof(struct foo, x) = 1
arr[0].x = 10
arr[1].x = 20
p0 = ffbff317
p1 = ffbff31c
Bus error

Her iki durumda da, program gcc packed.c -o packed sadece ekstra seçenekleri ile derlenmiş.

(Dizi yerine tek bir yapı kullanan bir program derleyici x üye düzgün bir şekilde tek bir adres üzerinde yapı ayırabilir beri güvenilir bir şekilde bu sorunu gösteren değil. struct foo iki nesne bir dizi ile, bir ya da diğer x yanlış hizalanmış bir üyesi olacaktır.)

Adı tarafından struct foo üye x söz konusu olduğunda, derleyici x potansiyel olarak yanlış hizalanmış ve ek kod doğru erişimi sağlayacak bilir.

arr[0].x arr[1].x Adres işaretçisi bir nesne içinde saklı edildikten sonra, ne derleyici ne de çalışan programı int yanlış hizalanmış bir nesneye işaret eden bilir. Sadece otobüs bir hata ya da benzer başka bir başarısızlık olarak düzgün bir şekilde yapıldı, sonuç (bazı sistemlerde) olduğunu varsayar.

Gcc bu tespit, sanırım, pratik olacaktır. Genel bir çözüm gerektirecek, her girişimi için başvuru bir işaretçi için her tür önemsiz olmayan uyum şartları da (a) ispat derleme zamanında bu işaretçi yok noktasına bir hizadan üyesi bir dolu yapı, veya (b) üreten hantal ve yavaş bir kod yapabilir ya da uyumlu meydana gelen nesneler.

gcc bug report bir teslim ettim. Dediğim gibi, pratik bunu düzeltmek olduğuna inanmıyorum, ama belgelere (şu anda yok) bahsetmeliyiz.

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

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Gigawipf

    Gigawipf

    18 ŞUBAT 2010
  • Mr_BrettHooge

    Mr_BrettHoog

    3 Ocak 2011
  • soyacincautv

    soyacincautv

    14 NİSAN 2010