编写跨平台代码时,ARM 不支持非对齐的内存访问,而 x86 支持。这一差异导致跨平台 C++ 代码容易出现 SIGBUS 问题。

SIGBUS 的含义是:该地址有效,但总线无法读取。具体的错误类型有以下三种:

  • BUS_ADRALN:未对齐的内存
  • BUS_ADRERR:不存在的物理地址
  • BUS_OBJERR:硬件错误

BUS_ADRALN 通常由类型转换导致,比如:

由于内存对齐,多出来的 3 个字节并没有被初始化为 0。当 ptr1 按照 int 类型解析内存时,能顺利读取后续 3 个字节,因为内存地址本身是合法的——尽管数据不正确。但如果地址未对齐,按 ptr1 的地址解析 int 就会出错:虽然 ptr1 指针的地址是合法的,但它只覆盖一个字节,并没有额外的 3 个字节。如果 CPU 支持非对齐内存访问,可以将这 3 个字节当做 0 处理,但部分 ARM 系列并不支持这种操作。因此,这类代码在跨平台编写时很容易引发 BUG。

解决方案

解决方案之一是:用 sizeofchar* 最小的基本数据内存块来对内存进行解析。

简单粗暴的做法是使用 memcpy(..,..,sizeof(…)),这样可以逐字节地将数据拷贝到副本中。

又比如: