EXC_BAD_ACCESS与结构对齐有关?

发布于 2025-01-05 17:41:38 字数 724 浏览 0 评论 0原文

在 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

这对我来说没有意义,所以经过几个小时的调试,我想知道这是否是某种对齐问题,所以我突发奇想尝试:

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

将 Pixel 的大小设置为 2 的幂。

这修复了EXC_BAD_ACCESS,但它非常奇怪。有人了解这里发生的事情吗?我只是通过填充结构来掩盖根本问题还是对齐确实会导致访问错误(我认为对齐只会影响性能,而不影响正确性)。

In an iOS application, I have a struct that looks like this

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

In my code, I allocate an array of these with calloc:

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

Now, this works perfectly in the simulator, but on the device, if I try to access buff[width * height - 1] (i.e. the last element in buff), I get an EXC_BAD_ACCESS.

This didn't make sense to me, so after a few hours of debugging, I wondered if it was some kind of alignment issue, so on a whim I tried:

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

making the size of Pixel a power of two.

This fixes the EXC_BAD_ACCESS, but it's awfully weird. Does anyone have any insight into what's going on here? Am I just masking the underlying problem by padding the struct or can alignment really cause a bad access (I thought alignment only had an effect on performance, not correctness).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

南七夏 2025-01-12 17:41:38

EXC_BAD_ACCESS 与对齐相关。与 x86 不同,ARM 要求内存访问与特定边界对齐。

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

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

EXC_BAD_ACCESS is related to alignment. Unlike x86, ARM requires memory access aligned to certain boundary.

To control alignment, use #pragma push, #pragma pack(n) and #pragma pop around.

See http://tedlogan.com/techblog2.html

攒眉千度 2025-01-12 17:41:38

这是对齐的问题。最小结构体对齐大小为 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,第二个 printf 语句将打印 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 个字节。

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

It is the problem of alignment. The minimum structure alignment size is 4 bytes and it will vary according to the datatype declaration in structure (eg. double).Here if you print the size of single block, it will print 3 instead of 4. But if you print the size of your structure, it will print 4 because of the minimum alignment size.

Assume if you also have an 'int' element in the structure, then both the size of single block and structure will be 8. This is because of compiler forced allocate padding byte in between the chars and the int. For example

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]));

The first printf statement will print 4 and the second will print 3. Because the default structure alignment size is 4 bytes and actual allocation is 3 bytes. Now just add one int type in to the same structure.

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]));

Here both printf statements will print 8. Because compiler forced to allocate a byte in between char and the int to just keep the alignment in to multiples of four. Then the structure will look like as given below,

typedef struct {

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

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

int i;
}MyType;

So you have to add a padding byte in your structure to keep the alignment because of the actual allocation is 3 bytes.

The structure allocation size also will vary according to the position of different datatype declarations inside the structure.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文