4

我注意到了一些非常奇怪的事情。说我定义了以下结构

typedef struct
{
  uint32_t a;
  uint16_t b;
  uint32_t c;
} foo;

这个结构包含在我从网络收到的一个大缓冲区中。

以下代码适用于 x86,但我SIGBUS在 ARM 上收到。

extern void * buffer;
foo my_foo;
my_foo = (( foo * ) buffer)[0];

用 memcpy 替换指针取消引用解决了这个问题。

在 ARM 中搜索 SIGBUS 让我发现这与内存对齐方式有关。

有人可以解释发生了什么吗?

4

4 回答 4

5

您自己说过:您的特定处理器存在内存对齐限制,并且buffer未对齐以允许从中读取大于一个字节的内容。该任务可能被编译成更大实体的三个动作。

有了memcpy(),就没有对齐限制,它必须能够在任意两个地址之间进行复制,所以它会做任何需要的事情来实现它。可能逐字节复制直到地址对齐,这是一种常见的模式。

顺便说一句,我发现在没有数组索引的情况下编写代码更清晰:

extern const void *buffer;
const foo my_foo = *(const foo *) buffer;
于 2013-10-01T11:09:26.283 回答
3

C 标准 [ISO/IEC 9899:2011] - 6.3.2.3,第 7 段:

指向对象或不完整类型的指针可以转换为指向不同对象或不完整类型的指针。如果结果指针未正确对齐指向的类型,则行为未定义。

来源:CERT 安全编码标准

于 2013-10-01T11:22:37.220 回答
1

基于 ARM 的系统期望结构在字边界上对齐。如果不是这种情况,您可以有不同的行为(例如,在 linux 内核中,这些行为在 中进行了描述,/proc/cpu/alignement其中之一是发送 SIGBUS)。

您所做的memcpy()是强制数据结构对齐。

于 2013-10-01T11:25:52.183 回答
0

不久前,我在飞思卡尔 imx 上开发了一些下载应用程序……那里有内存对齐问题(要求可执行文件是 512 字节的倍数)……arm 和 x86 之间的根本区别……但是事情记住 memcpy 是逐字节复制...所以,它可能有效,但请务必检查运行时问题...不要被 memcpy 愚弄...拥有内存总是一个好主意为您的特定平台对齐结构。

于 2013-10-01T11:46:07.863 回答