6

我试图了解堆栈对齐是如何工作的,如什么是“堆栈对齐”中所述?但我很难找到一个小例子来证明上述行为。我正在检查我的函数 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 字节的块分配。在堆栈分配、填充和对齐中讨论了一个类似的主题,但我更想知道的是为什么对齐在我的示例中没有效果。

4

5 回答 5

5

我认为你错过了一个事实,即所有堆栈变量都不需要单独对齐到 16 字节边界。

于 2011-01-27T14:28:45.560 回答
0

我从未听说过诸如特定堆栈对齐之类的事情。如果对 CPU 有对齐要求,则在各种数据存储器上进行对齐,无论它是存储在堆栈上还是其他地方。它从偶数地址开始,后面有 16、32 或 64 位数据。

16 字节可能是某种片上高速缓存优化,尽管这对我来说似乎有点牵强。

于 2011-01-27T14:54:18.027 回答
0

通常的规则是在 32 位边界上分配变量。我不确定您为什么认为 16 字节有任何特殊含义。

于 2011-01-27T14:29:11.097 回答
0

一个很好的例子是在结构上看到这一点。

struct a{
    int a;
    char b;
    int c;
} a;

在 32 位系统上,如果单独使用,这将是 4+1+4 字节。

因为结构和它的成员是对齐的,所以“char b”将是 4 个字节,将其变为 12 个字节。

struct b{
    int a;
    char b;
    int c;
} __attribute__((__packed__)) b;

使用 packed 属性,您可以强制它保持最小尺寸。因此这个结构是 9 个字节。

你也可以检查这个http://sig9.com/articles/gcc-packed-structures

希望它有所帮助。

于 2011-01-27T15:51:54.170 回答
0

您可以使用名为 pahole http://packages.debian.org/lenny/dwarves的工具检查如何为您的数据结构分配额外的内存。它向您展示了程序的所有漏洞:数据的大小(如果您总结的话)以及在您卡住时分配的实际大小

于 2011-12-17T14:12:05.133 回答