EXC_BAD_ACCESS与struct alignment有关吗?

时间:2012-02-13 03:40:23

标签: objective-c c ios exc-bad-access memory-alignment

在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,但它非常奇怪。有没有人对这里发生的事情有任何见解?我只是通过填充结构来掩盖底层问题,或者对齐确实会导致访问不良(我认为对齐只会影响性能,而不是正确性)。

2 个答案:

答案 0 :(得分:3)

EXC_BAD_ACCESS is related to alignment.与x86不同,ARM要求内存访问与某些边界对齐。

要控制对齐方式,请使用#pragma push#pragma pack(n)#pragma pop

请参阅http://tedlogan.com/techblog2.html

答案 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个字节。

结构分配大小也会根据结构内不同数据类型声明的位置而变化。