int32_t的对齐要求:gcc / linux 86 vs amd64

时间:2015-05-18 09:39:38

标签: c linux gcc intel c99

首先我们谈谈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

原始问题来自这里(俄语): https://ru.stackoverflow.com/questions/268888/%D0%9E%D0%BF%D1%8F%D1%82%D1%8C-%D0%BE%D0%B1-%D0%BE%D0%BF%D1%82%D0%B8%D0%BC%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D0%B8-gcc-o3-intel-i5-2500-segmentation-fault

2 个答案:

答案 0 :(得分:1)

编译和链接很好意味着什么,在运行时发生未定义的行为。就C标准而言,代码可能会也可能不会调用UB。

6.3.2.3/7:

  

指向对象类型的指针可以转换为指向a的指针   不同的对象类型。如果结果指针不正确   对于引用的类型,行为是未定义的。

术语“正确对齐”取决于CPU架构。如果您的CPU没有对齐限制,则uint32_t指针将被视为正确对齐,然后您将没有UB。

如果CPU允许错位访问,但会导致代码效率降低,那么你也没有UB。

但如果CPU不支持错位访问,则代码为UB。

答案 1 :(得分:1)

x86和x64指令集都允许未对齐访问,而不会导致未定义的行为,但SIMD扩展指令集除外。

x86 / x64中的代码问题是由于别名冲突而调用未定义的行为。由于您已使用gcc扩展程序,因此可以使用-fno-strict-aliasing停用别名规则。