在iOS应用程序中,我有一个看起来像这样的结构
typedef struct _Pixel {
signed char r;
signed char g;
signed char b;
} Pixel;
在我的代码中,我使用calloc分配了这些数组:
Pixel* buff = calloc(width * height, sizeof(Pixel));
现在,这在模拟器中完美运行,但在设备上,如果我尝试访问buff[width * height - 1]
(即buff
中的最后一个元素),我会得到EXC_BAD_ACCESS
。< / p>
这对我来说没有意义,所以经过几个小时的调试后,我想知道这是不是某种对齐问题,所以我一直想着:
typedef struct _Pixel {
signed char r;
signed char g;
signed char b;
signed char padding;
} Pixel;
使Pixel的大小为2的幂。
这修复了EXC_BAD_ACCESS
,但它非常奇怪。有没有人对这里发生的事情有任何见解?我只是通过填充结构来掩盖底层问题,或者对齐确实会导致访问不良(我认为对齐只会影响性能,而不是正确性)。
答案 0 :(得分:3)
EXC_BAD_ACCESS is related to alignment.与x86不同,ARM要求内存访问与某些边界对齐。
要控制对齐方式,请使用#pragma push
,#pragma pack(n)
和#pragma pop
。
答案 1 :(得分:2)
这是对齐的问题。最小结构对齐大小为4个字节,它将根据结构中的数据类型声明而变化(例如,double)。如果您打印单个块的大小,它将打印3而不是4.但如果您打印的大小你的结构,由于最小的对齐尺寸,它将打印4。
假设你在结构中也有一个'int'元素,那么单个块和结构的大小都是8.这是因为编译器在chars和int之间强制分配填充字节。例如
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]));
第一个printf语句将打印4,第二个将打印3.因为默认结构对齐大小为4个字节,实际分配为3个字节。现在只需将一个int类型添加到同一个结构中。
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]));
这里两个printf语句都会打印8.因为编译器强制在char和int之间分配一个字节,只是将对齐保持为四的倍数。然后结构将如下所示,
typedef struct {
signed char r;
signed char g;
signed char b;
char padding; // Padding byte allocated to keep alignment.
int i;
}MyType;
因此,您必须在结构中添加填充字节以保持对齐,因为实际分配是3个字节。
结构分配大小也会根据结构内不同数据类型声明的位置而变化。