C Linux中的结构分配在ARM中失败,但在x86中成功
我注意到了一些非常奇怪的事情。 假设我已经定义了以下结构C Linux中的结构分配在ARM中失败,但在x86中成功,c,linux,arm,memory-alignment,sigbus,C,Linux,Arm,Memory Alignment,Sigbus,我注意到了一些非常奇怪的事情。 假设我已经定义了以下结构 typedef struct { uint32_t a; uint16_t b; uint32_t c; } foo; 这个结构包含在我从网络接收的一个大缓冲区中 以下代码在x86中工作,但我在ARM上接收到SIGBUS extern void * buffer; foo my_foo; my_foo = (( foo * ) buffer)[0]; 用memcpy替换指针解引用解决了问题。 通过在ARM中搜索SIGBUS
typedef struct
{
uint32_t a;
uint16_t b;
uint32_t c;
} foo;
这个结构包含在我从网络接收的一个大缓冲区中
以下代码在x86中工作,但我在ARM上接收到SIGBUS
extern void * buffer;
foo my_foo;
my_foo = (( foo * ) buffer)[0];
用memcpy替换指针解引用解决了问题。
通过在ARM中搜索SIGBUS,我发现这与内存对齐有关
有人能解释一下发生了什么吗?你自己说的:在你的特定处理器上有内存对齐限制,
缓冲区没有正确对齐以允许从中读取大于一个字节的数据。任务可能被编译成三个较大实体的移动
使用memcpy()
,没有对齐限制,它必须能够在任意两个地址之间进行复制,因此它可以执行实现该功能所需的任何操作。可能是逐字节复制直到地址对齐,这是一种常见模式
另一方面,我发现编写代码时不使用数组索引更为清晰:
extern const void *buffer;
const foo my_foo = *(const foo *) buffer;
C标准[ISO/IEC 9899:2011]-6.3.2.3,第7段:
指向对象或不完整类型的指针可以转换为指向其他对象或不完整类型的指针如果结果指针未正确对齐指向的类型,则行为未定义。
基于ARM的系统希望结构在单词边界上对齐。如果不是这样,您可以有不同的行为(例如在linux内核中,这些行为在/proc/cpu/alignment
中描述,其中之一是发送SIGBUS)
您使用memcpy()
所做的是强制数据结构对齐。一段时间前,我在飞思卡尔imx上开发了一些下载应用程序……内存对齐有问题(要求可执行文件是512字节的倍数)…arm和x86之间的根本区别…但memcpy需要记住的是,它可以逐字节复制…因此,它可能会工作,但请确保检查运行时问题…不要被memcpy愚弄…为您的特定平台提供内存对齐的结构始终是一个好主意。Google:请参阅。对齐和结束是一个永恒的主题。即使手臂支持这个,它也会在一个大端CPU上断裂。您需要将struct
注释为已打包,或者memcpy()
可以工作(不是SIGBUS
),但它不能正常工作。有一些关于ARM Linux这个问题的附加信息。然而,我认为你的潜在机制是有缺陷的。有很多序列化例程、协议和框架(ntohl()
、ntohs()
、JSON等等)。@artlessnoise感谢您的评论,但是为什么要使用-1呢?