我刚刚阅读了问题是否未对齐的内存访问总是会导致总线错误?链接到 Wikipedia 文章Segmentation Fault。
在这篇文章中,有一个非常罕见的英特尔处理器标志AC aka Alignment Check 的精彩提醒。
这是启用它的方法(来自维基百科的总线错误示例,为 x86-64 System V 修复了一个红色区域破坏错误,因此这在 Linux 和 MacOS 上是安全的,并且从基本 asm 转换而来,这在函数内部从来都不是一个好主意:您希望对 AC 的更改按照内存访问进行排序。
#if defined(__GNUC__)
# if defined(__i386__)
/* Enable Alignment Checking on x86 */
__asm__("pushf\n orl $0x40000,(%%esp)\n popf" ::: "memory");
# elif defined(__x86_64__)
/* Enable Alignment Checking on x86_64 */
__asm__("add $-128, %%rsp \n" // skip past the red-zone, in case there is one and the compiler has local vars there.
"pushf\n"
"orl $0x40000,(%%rsp)\n"
"popf \n"
"sub $-128, %%rsp" // and restore the stack pointer.
::: "memory"); // ordered wrt. other mem access
# endif
#endif
一旦启用,它的工作原理很像 ARM 对齐设置/proc/cpu/alignment
,请参阅答案如何捕获未对齐的内存访问?举些例子。
此外,如果您使用的是 GCC,我建议您启用-Wcast-align
警告。在为具有严格对齐要求的目标(例如 ARM)构建时,GCC 将报告可能导致内存访问未对齐的位置。
但请注意,libc 为 memcpy 和其他功能编写的手写 asm 仍然会进行未对齐的访问,因此在 x86(包括 x86-64)上设置 AC 通常不实用。GCC 有时会发出 asm 进行非对齐访问,即使您的源没有,例如,作为一次复制或归零两个相邻数组元素或结构成员的优化。