【发布时间】:2015-07-29 18:05:48
【问题描述】:
首先我们谈谈 gcc/linux(x86, amd64) 和 c99。
代码如下:
#include <stdint.h>
void f(void *p)
{
uint32_t *num = p;
*num = 17;
}
int main()
{
char buf[8] __attribute__ ((aligned (8)));
f(&buf[3]);
}
问题是UB吗?
一方面,英特尔 CPU 允许非对齐访问, 从另一只手我发现了这个: http://www.uclibc.org/docs/psABI-i386.pdf http://www.x86-64.org/documentation/abi.pdf 并且他们都提到了4字节整数的4字节对齐。
所以即使它编译并且工作正常,它仍然是 UB 吗? 因为 gcc 认为“uint32_t *”指针的值指向 4字节对齐地址, 并毫不犹豫地在“f”函数中使用例如“SSE”?
gcc 维护者认为这样的代码是“未定义代码”: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66194
【问题讨论】:
-
stackoverflow.com/q/9608171/995714 gcc 将假定指针未对齐,除非您已指定
-
实际上在上面的链接中,gcc 假设“float*”对齐 4,而不是“未对齐”,再加上这个关于 ARM 架构的话题,不清楚英特尔的情况是否相同。跨度>
-
你可以随时反汇编代码,看看它产生了什么指令。
-
在实际代码中 gcc 生成导致 seg 错误的指令(它使用 SSE),所以问题的答案将是它是 gcc 错误还是程序员编写了代码错误。
-
对于像这样明确导致访问不对齐的代码,我认为它要求编译器自动将代码转换为正确对齐的东西。这是编译器应该放手的情况,因为程序员已经告诉它他们知道自己在做什么。他们是否真的知道自己在做什么取决于特定的 CPU:如果 CPU 无法处理它,那么它是程序员引起的错误,就像未定义行为的情况一样。