9

(Sorry in advance for not having managed to reduce my problem to a simple failing test case...)

I have faced issues with upgrading to GCC 6.3.0 to build our codebase (relevant flags: -O3 -m32).

Specifically, my application segfaults within a struct ctor call because of GCC optimizations.

In this ctor, GCC used movaps :

movaps %xmm0,0x30a0(%ebx)

movaps requires the operand to be 16-byte aligned. But at this point in time, %ebx points to my object, which is not necessarily 16-byte aligned. From glibc :

“The address of a block returned by malloc or realloc in GNU systems is always a multiple of eight (or sixteen on 64-bit systems).“</p>

Hence the segfault (when built with -O3 -m32).

Why does it seem like GCC assumed the allocated object would be 16-byte aligned ? Am I misunderstanding something ?

Notes:

  • No alignment hints or attributes on this struct
  • Object has been initialized via default new operator
  • Depends on the level of optimization:
    • PASS: -m32 -O2
    • FAIL: -m32 -O2 -ftree-slp-vectorize
    • PASS: -m32 -O3 -fno-tree-slp-vectorize
    • FAIL: -m32 -O3

This other project, seem to have hit similar issues : https://github.com/godotengine/godot/issues/4623

Their investigation points to -fvect-cost-model=dynamic. Investigation on my codebase rather points to -ftree-slp-vectorize.

4

1 回答 1

2

编译器可能有理由认为该对象的对齐方式≥ 16 个字节。alignof()通过使用C++11 中的运算符,可以找出编译器认为对齐是什么。__alignof__GCC 有一个可用于 C 和更早 C++ 版本的扩展。

结构的对齐方式是其中任何东西的最高对齐方式,递归。那里可能有比预期更高的对齐方式。

虽然 C++11 标准保证返回的内存new与任何对象的“基本对齐要求”所需的值对齐,但这仅适用于标准类型和由它们组成的对象。使用 C++11alignas()__attribute__((aligned(x)))GCC 扩展来请求更高的对齐可能会超出new提供的范围。

对此的解决方案是使用std::aligned_alloc()(C++11 或更高版本) 或posix_memalign()(POSIX-only but < C++11) 来获得对齐的内存。这可以与运算符的放置形式相结合,以new在该内存或特定类运算符重载中构造对象newand delete

于 2017-02-17T23:33:58.037 回答