gpt4 book ai didi

gcc - 栈分配,为什么要多出空间?

转载 作者:行者123 更新时间:2023-12-05 00:00:38 25 4
gpt4 key购买 nike

我玩了一会儿,以更好地掌握调用约定和堆栈的处理方式,但我无法弄清楚为什么 main 在设置堆栈时分配了三个额外的双字(在 <main+0> 处)。它既不是 8 字节也不是 16 字节对齐,所以据我所知,这不是原因。正如我所见, main 需要 12 个字节来表示 func 和返回值的两个参数。

我错过了什么?

该程序是在 x86 架构上使用“gcc -ggdb”编译的 C 代码。

编辑:我从 gcc 中删除了 -O0 标志,它对输出没有影响。

(gdb) disas main
Dump of assembler code for function main:
0x080483d1 <+0>: sub esp,0x18
0x080483d4 <+3>: mov DWORD PTR [esp+0x4],0x7
0x080483dc <+11>: mov DWORD PTR [esp],0x3
0x080483e3 <+18>: call 0x80483b4 <func>
0x080483e8 <+23>: mov DWORD PTR [esp+0x14],eax
0x080483ec <+27>: add esp,0x18
0x080483ef <+30>: ret
End of assembler dump.

编辑:当然我应该发布 C 代码:
int func(int a, int b) {
int c = 9;
return a + b + c;
}

void main() {
int x;
x = func(3, 7);
}

平台是 Arch Linux i686。

最佳答案

当您进入函数时,函数的参数(包括但不限于 main )已经在堆栈中。您在函数内部分配的空间用于局部变量。对于具有简单返回类型的函数,例如 int ,返回值通常在寄存器中( eax ,在 x86 上使用典型的 32 位编译器)。

例如,如果 main是这样的:

int main(int argc, char **argv) { 
char a[35];

return 0;
}

...当我们进入 main 为 a 腾出空间时,我们希望看到堆栈上至少分配了 35 个字节。 .假设是 32 位实现,通常会向上取整为 4 的下一个倍数(在本例中为 36)以保持堆栈的 32 位对齐。我们不希望看到为返回值分配的任何空间。 argcargv将在堆栈上,但它们在 main 之前已经在堆栈上已输入,所以 main不需要做任何事情来为他们分配空间。

在上述情况下,在为 a 分配空间后, a通常从 [esp-36] 开始, argv将在 [esp-44]argc将在 [esp-48] (或者这两个可能会颠倒——取决于参数是从左到右还是从右到左)。如果你想知道我为什么跳过 [esp-40] ,那将是返回地址。

编辑:这是函数入口处和设置堆栈框架后的堆栈图:

enter image description here

编辑 2:根据您更新的问题,您所拥有的有点迂回,但并不是特别难以理解。进入 main ,它不仅为 main 的局部变量分配空间,还有你传递给你从 main 调用的函数的参数.

这至少占了分配的一些额外空间(尽管不一定是全部)。

关于gcc - 栈分配,为什么要多出空间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9862017/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com