【发布时间】:2017-07-05 10:11:26
【问题描述】:
(很抱歉未能将我的问题简化为一个简单的失败测试用例......)
我在升级到 GCC 6.3.0 以构建我们的代码库时遇到了问题(相关标志:-O3 -m32)。
具体来说,由于 GCC 优化,我的应用程序在 struct ctor 调用中出现段错误。
在这个ctor中,GCC使用了movaps:
movaps %xmm0,0x30a0(%ebx)
movaps 要求操作数16字节对齐。但此时,%ebx 指向我的对象,该对象不一定是 16 字节对齐。来自 glibc:
“在 GNU 系统中 malloc 或 realloc 返回的块地址总是 8 的倍数(或 64 位系统中的 16)。”
因此出现段错误(使用 -O3 -m32 构建时)。
为什么 GCC 似乎假定分配的对象是 16 字节对齐的?我是不是误会了什么?
注意事项:
- 此结构没有对齐提示或属性
- 对象已通过默认
new运算符初始化 - 取决于优化级别:
- 通过:
-m32 -O2 - 失败:
-m32 -O2 -ftree-slp-vectorize - 通过:
-m32 -O3 -fno-tree-slp-vectorize - 失败:
-m32 -O3
- 通过:
这个其他项目,似乎也遇到了类似的问题:https://github.com/godotengine/godot/issues/4623
他们的调查指向-fvect-cost-model=dynamic。对我的代码库的调查宁愿指向-ftree-slp-vectorize。
【问题讨论】:
-
在你的对象上使用
alignof会告诉你编译器认为它需要什么对齐。听起来它不应该≥16,但检查起来会很痛苦。 -
拥有
alignof==16不是错误,但这意味着你不能使用glibc 的malloc。再说一次,标准限制了实现的malloc,而不是操作系统的malloc。 GCC 可能需要包装 glibc。 (我认为无论如何都应该这样做) -
alignof返回64。alignof(max_align_t)返回8(预期)。对对象或其成员的对齐没有用户要求;为什么alignof会是64?我没有直接使用malloc,而是假设new正在使用它。 -
好吧好吧好吧……在结构深处几层,我刚刚找到了缓存行大小所需的对齐方式。这就是
alignof==64的全部原因。正如@TrentP 和@MSalters 指出的那样,这也意味着我不能使用8 字节对齐的new。由于 GCC 没有利用整体对齐的优势,因此曾经偶然使用以前的版本和较少的优化... -
(请随意让您的 cmets 回答让我验证)
标签: c++ gcc glibc memory-alignment gcc6