Objective c EXC\u与结构对齐相关的错误访问?

Objective c EXC\u与结构对齐相关的错误访问?,objective-c,c,ios,exc-bad-access,memory-alignment,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中的最后一个元素),我会

在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\u BAD\u访问

这对我来说毫无意义,所以经过几个小时的调试后,我想知道这是否是某种对齐问题,于是一时兴起,我尝试:

typedef struct _Pixel {
  signed char r;
  signed char g;
  signed char b;
  signed char padding;
} Pixel;
使像素的大小为2的幂

这修复了
EXC\u BAD\u访问
,但它非常奇怪。有人知道这里发生了什么吗?我只是通过填充结构来掩盖潜在的问题,还是对齐真的会导致错误访问(我认为对齐只会影响性能,而不会影响正确性)。

EXC_bad_访问与x86不同,ARM需要按照特定边界对齐内存访问

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


参见

这是对齐问题。最小结构对齐大小为4字节,它将根据结构中的数据类型声明而变化(例如double)。在这里,如果您打印单个块的大小,它将打印3而不是4。但是,如果打印结构的大小,由于最小对齐大小,它将打印4

假设在结构中还有一个“int”元素,那么单块和结构的大小都是8。这是因为编译器强制在字符和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之间分配一个字节,以便将对齐方式保持为4的倍数。然后结构将如下所示

typedef struct {

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

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

int i;
}MyType;
因此,必须在结构中添加一个填充字节以保持对齐,因为实际分配是3个字节


根据不同数据类型声明在结构中的位置,结构分配大小也会有所不同。

请注意两件事。因为SO不允许我编辑一个字符,所以您在calloc中有一个输入错误。你在结尾缺少一个括号。至于你的主要问题,如果你真的把buff放到其他地方,或者在你访问它的某个时候,你碰巧不小心偏离了索引,这种事情通常会发生。在尝试访问最后一个元素之前,您是否还做了任何其他的buff操作?再次检查您的宽度和高度值。。。!!!这是已经运行了几个月的代码——唯一的区别是我将结构成员的类型从CGFloat更改为有符号字节。所以宽度和高度不是问题——这与结构的布局有关。你能包括你用来访问它的行吗?你是想设置整个像素,还是只是其中的一个字段?他没有问如何控制对齐。他问是否有人知道为什么在没有填充物的情况下,它首先会导致EXC_BAD_访问错误对齐是导致手臂上EXC_BAD_访问错误的原因。不要认为x86上的行为是理所当然的。这很奇怪,因为他正在访问字节,而字节不应该出现对齐异常。可能结构被传递到应用程序的某个部分,而该部分在结构更改后没有重新编译?
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]));