2012-02-13 18 views
5

, benim kodunda buEXC_BAD_ACCESS? iOS uygulamasında

typedef struct _Pixel { 
    signed char r; 
    signed char g; 
    signed char b; 
} Pixel; 

benzeyen bir yapı var, calloc bu bir dizi tahsis:

Pixel* buff = calloc(width * height, sizeof(Pixel)); 

Şimdi, bu simülatörde mükemmel çalışıyor ancak aygıtta, buff[width * height - 1] (buff öğesinde son öğe) erişmeye çalışırsanız, bir EXC_BAD_ACCESS alırsınız.

Bu bana mantıklı değildi, bu yüzden hizalama sorunu bir tür olsaydı bir heves denedim böylece hata ayıklama birkaç saat sonra, ben, merak:

typedef struct _Pixel { 
    signed char r; 
    signed char g; 
    signed char b; 
    signed char padding; 
} Pixel; 

boyutunu yapma Piksel, ikisinin gücü.

Bu, EXC_BAD_ACCESS düzeltir, ancak çok tuhaftır. Burada neler olup bittiği hakkında herhangi bir bilgisi yok mu? Sadece altta yatan sorunu maskeleme yaparak maskeleme ya da hizalama gerçekten kötü bir erişime neden olabilir (hizalamanın sadece performans üzerinde değil, doğrulukta bir etkisi olduğunu düşündüm).

+0

Hey Bill iki şey. SO bir karakteri düzenlememe izin vermediğinden, calloc'ta yazım hatası var. Sonunda parantez eksik. Ana sorununuza gelince, bu tür bir şey genellikle Ya da başka bir yerde tutkuyu yeniden birleştirirseniz ya da eriştiğiniz zamanlardan birinde yanlışlıkla dizin dışı kalmanız durumunda olur. Son öğeye erişmeye çalışmadan önce * buff * 'a başka bir şey yapar mı? – Lefteris

+0

genişlik ve yükseklik değerlerinizi tekrar kontrol edin ... !!! –

+0

Bu, aylarca çalışan bir koddur - tek fark, CGFloat'tan yapı üyelerinin türünü imzalı baytlara değiştirdiğimdir. Yani genişlik ve yükseklik sorun değil - yapının düzeni ile ilgili bir şey. – Bill

cevap

3

EXC_BAD_ACCESS is related to alignment. x86'dan farklı olarak, ARM belirli sınırlarla hizalanmış bellek erişimi gerektirir.

Hizalamayı denetlemek için, #pragma push, #pragma pack(n) ve #pragma pop kullanın.

Bu hizalanma sorun http://tedlogan.com/techblog2.html

+2

Hizalamayı nasıl kontrol edeceğini sormadı. Fular olmaksızın neden EXC_BAD_ACCESS'e yol açtığını kimse bilip bilmediğini sordu – Lefteris

+0

Yanlış hizalama, ARM üzerinde EXC_BAD_ACCESS'in nedenidir. X86'daki davranışları kabul edilmez. – ZhangChn

+0

tuhaftır, çünkü hizalama istisnalarından etkilenmeyen baytlara erişir. Belki de yapının, yapının değişmesinden sonra yeniden derlenmeyen uygulamanın bir kısmına geçilir. –

2

bakınız. Minimum yapı hizalama boyutu 4 bayttır ve yapıdaki veri türü bildirimine göre değişecektir (örn. Çift). Tek blok boyutunu yazdırırsanız 4 yerine 3 yazdıracaktır. Ancak, Yapınızın, minimum hizalama boyutu nedeniyle 4 yazdıracaktır.

Ayrıca, yapısında bir 'int' öğeniz varsa, o zaman her iki bloğun ve yapının boyutunun 8 olacağını varsayalım. Bunun nedeni, derleyici tarafından chars ve int. Örnek

typedef struct { 

signed char r; 
signed char g; 
signed char b; 
}MyType; 

MyType *type = (MyType *)calloc(20, sizeof(MyType)); 
printf("size: %ld", sizeof(MyType)); 
printf("size: %ld", sizeof(type[0])); 

için ilk printf ifadesi 4 baskı ve varsayılan yapı hizalama boyutu 4 byte kadardır ve gerçek ayırma 3 bayt olduğu için, ikinci 3. yazdırılır. Şimdi sadece aynı yapıya bir int tipi ekleyin. derleyici sadece dört katları için hizalama tutmak için char ve int arasında bir bayt tahsis etmek zorunda Çünkü

İşte hem printf ifadeleri
typedef struct { 

signed char r; 
signed char g; 
signed char b; 

int i;   // New int element added here 
}MyType; 

MyType *type = (MyType *)calloc(20, sizeof(MyType)); 
printf("size: %ld", sizeof(MyType)); 
printf("size: %ld", sizeof(type[0])); 

8. yazdırılır. Sonra yapısı

typedef struct { 

signed char r; 
signed char g; 
signed char b; 

char padding; // Padding byte allocated to keep alignment. 

int i; 
}MyType; 

Yani çünkü gerçek tahsisi uyum tutmak için yapısında bir dolgu bayt eklemek zorunda, aşağıda verildiği gibi nasıl görüneceğini 3 bayt. Yapı ayırma boyutu, yapı içindeki farklı veri türü bildirimlerinin konumuna göre de değişecektir.