GCC6.2.0与GCC8.3.0局部变量栈对齐差异如何消除?
差异根因
这个差异来自两个GCC版本默认的栈对象排布策略不同:
你定义的struct foo只包含char数组,自身对齐要求仅为1字节,实际占用空间是12字节。GCC 6.2默认会把每个栈上的局部变量都单独对齐到默认的16字节栈边界,所以每个foo对象后面会多补4字节空白,两个对象的地址差就是16字节。GCC 8.3默认开启了栈空间紧凑优化,对于自身对齐要求低于栈边界的小对象,只会保证满足它本身的对齐要求,不会额外加空白填充,所以两个foo对象地址差就是实际的12字节。
你之前用的-mpreferred-stack-boundary=4只控制整个栈帧的整体对齐边界,管不到单个小对象的排布规则,所以加了也没用。
消除差异的方法
你可以选任意一种方案对齐两个版本的行为:
让两个版本都按16字节对齐分配
两种实现方式:
- 改代码:给
struct foo显式指定16字节对齐,修改后的代码如下:
#include <iostream> struct foo { char c[12]; } __attribute__((aligned(16))); int main() { foo fa; foo fb; std::cout << &fa << "\n"; std::cout << &fb << "\n"; }
- 改编译参数:给GCC 8.3加上编译选项
-fno-conserve-stack -mstack-alignment=16,就能恢复到GCC 6.2的栈对齐逻辑。
让两个版本都按12字节紧凑分配
给GCC 6.2加上编译选项 -fconserve-stack,开启栈空间紧凑优化,两个对象的地址差就会变成12字节,和GCC 8.3默认行为一致。
内容的提问来源于stack exchange,提问作者user8449964
相关产品推荐
相关产品推荐

