为什么GCC 6假定数据是16字节对齐的? [英] Why does GCC 6 assume data is 16-byte aligned?

查看:71
本文介绍了为什么GCC 6假定数据是16字节对齐的?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(对不起,未能将我的问题简化为一个简单的失败的测试用例...)

我在升级到GCC 6.3.0来构建代码库时遇到了问题(相关标志: -O3 -m32 ).

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

具体地说,由于GCC优化,我的应用程序在struct ctor调用中出现段错误.

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

在此ctor中,GCC使用了 movaps :

In this ctor, GCC used movaps :

movaps %xmm0,0x30a0(%ebx)

movaps 需要操作数 16字节对齐.但是在此时,%ebx 指向我的对象,该对象未必是16字节对齐.来自glibc:

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 :

在GNU系统中,由malloc或realloc返回的块的地址始终为8的倍数(在64位系统上为16)."

"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)."

发生段故障(使用 -O3 -m32 构建时).

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

为什么看起来好像GCC假定分配的对象将对齐16字节?我误会了吗?

注意:

  • 此结构上没有对齐提示或属性
  • 对象已通过默认的 new 运算符
  • 进行了初始化
  • 取决于优化级别:
    • 通过: -m32 -O2
    • 失败: -m32 -O2 -ftree-slp-vectorize
    • 通过: -m32 -O3 -fno-tree-slp-vectorize
    • 失败: -m32 -O3
    • 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

      这个其他项目似乎遇到了类似的问题: https://github.com/godotengine/godot/issues/4623

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

      他们的调查指向 -fvect-cost-model = dynamic .在我的代码库上进行的调查指向了 -ftree-slp-vectorize .

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

      推荐答案

      编译器可能有理由认为对象的对齐方式≥16个字节.通过使用C ++ 11中的 alignof()运算符,可以找出编译器认为对齐的内容.GCC具有扩展名 __ alignof __ ,可在C和早期C ++版本中使用.

      It's possible that the compiler has a reason to think the object has an alignment ≥ 16 bytes. It's possible to find out what the compiler thinks the alignment is by using the alignof() operator in C++11. GCC has an extension __alignof__ that is available in C and earlier C++ versions.

      结构的对齐方式是其中所有内容的最高对齐方式,它是递归的.那里可能有比预期更高的对齐方式.

      A structure's alignment is the highest alignment of anything in it, recursively. There could be something in there with higher alignment than expected.

      尽管C ++ 11标准保证 new 返回的内存与任何对象的基本对齐要求"所需的值对齐,但这仅适用于标准类型和由这些对象组成的对象他们.使用C ++ 11 alignas() __ attribute __((aligned(x))) GCC扩展来请求更高的对齐方式可能会超出 new 提供.

      While the C++11 standard guarantees that memory returned by new is aligned to the value needed by the "fundamental alignment requirement" of any object, this only applies to standard types and objects made of them. Using C++11 alignas() or the __attribute__((aligned(x))) GCC extension to request higher alignment might exceed what new provides.

      对此的一种解决方案是使用 std :: aligned_alloc()(C ++ 11或更高版本)或 posix_memalign()(仅POSIX,但<C ++ 11)以获取对齐的内存.这可以与 new 运算符的放置形式一起在内存中构造对象,或者 new delete 的特定于类的运算符重载.

      A solution to this would be to use std::aligned_alloc() (C++11 or later) or posix_memalign() (POSIX-only but < C++11) to get aligned memory. This could be coupled with the placement form of the new operator to construct the object in that memory or class specific operator overloads of new and delete.

      这篇关于为什么GCC 6假定数据是16字节对齐的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆