我正试图像what is "stack alignment"?中描述的那样理解堆栈对齐是如何工作的,但我很难获得一个小示例来演示上述行为。我正在检查函数foo的堆栈分配:
void foo() {
int a = 0;
char b[16];
b[0] = 'a';
}我用gcc -ggdb example.c -o example.out (即没有任何编译器标志)编译源文件,来自gdb的汇编程序转储如下:
(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>: push %ebp
0x08048395 <+1>: mov %esp,%ebp
0x08048397 <+3>: sub $0x20,%esp
0x0804839a <+6>: movl $0x0,-0x4(%ebp)
0x080483a1 <+13>: movb $0x61,-0x14(%ebp)
0x080483a5 <+17>: leave
0x080483a6 <+18>: ret
End of assembler dump.我的堆栈以16字节的块分配(我用其他几个测试验证了这一点)。根据这里的汇编程序转储,分配了32个字节,因为(16 < 4+16 < 32),但是我期望在前16个字节上分配整数'a‘,然后在接下来的16个字节上分配字符数组(留下12个字节之间的空间)。但是,整数和字符数组似乎都被分配了20个字节的连续块,正如我前面提到的讨论所示,这是低效的。有人能解释一下我在这里错过了什么吗?
编辑:我得出的结论是,我的堆栈以16字节的块分配,程序如下所示:
void foo() {
char a[1];
}以及相应的汇编程序转储:
(gdb) disassemble foo
Dump of assembler code for function foo:
0x08048394 <+0>: push %ebp
0x08048395 <+1>: mov %esp,%ebp
0x08048397 <+3>: sub $0x10,%esp
0x0804839a <+6>: leave
0x0804839b <+7>: ret
End of assembler dump.您可以看到,在堆栈上为大小为1的字符数组分配了16个字节(只需要1个字节)。我可以将数组的大小增加到16,汇编程序转储保持不变,但是当它是17时,它会在堆栈上分配32个字节。我运行了许多这样的示例,结果是相同的;堆栈内存以16字节的块分配。Stack allocation, padding, and alignment中也讨论过类似的主题,但我更想了解的是为什么在我的示例中对对齐没有影响。
发布于 2011-01-27 14:28:45
我认为您忽略了这样一个事实,即不需要所有堆栈变量单独对齐到16字节的边界。
发布于 2011-12-17 14:12:05
您可以使用名为pa孔http://packages.debian.org/lenny/dwarves的工具检查如何为您的数据结构分配额外的内存。它显示了程序的所有漏洞:如果你把它加起来的话,你的数据的大小,以及在你被卡住的时候分配的真实大小。
发布于 2011-01-27 14:29:11
通常的规则是在32位边界上分配变量。我不知道你为什么认为16个字节有什么特殊意义。
https://stackoverflow.com/questions/4817473
复制相似问题