关于函数调用堆栈的混淆
根据维基:
调用者将返回地址压入堆栈,被调用的子例程一旦完成,就会从调用堆栈中弹出返回地址并将控制转移到该地址。
来自Wiki的图片:
我不太明白这一点。 说我有一个C程序如下:
#include int foo(int x) { return x+1; } void spam() { int a = 1; //local variable int b = foo(a); //subroutine called int c = b; //local variable } int main() { spam(); return 0; }
我认为调用堆栈应该类似于绘图,如下所示:
means none local variables or params _| parameters for foo() |_ top | local of spam() | ^ | return address of foo() |<---foo() called, when finishes, return here? | | local of spam() | bot | local of spam() | _| parameters for spam() |_ | locals of main() | | return address of spam() |<---spam() called, when finishes, return here? | parameters for main() |
题:
根据Wiki引用的字样,
被调用的子程序,当它完成时,从调用堆栈中弹出返回地址并将控制转移到该地址。
我的抽签是对的吗?
2.如果它是正确的,那么当foo()完成时,它会
弹出调用堆栈的返回地址并将控制权转移到该地址
,但它如何弹出退货地址? 因为当foo完成时,当前的堆栈指针指向垃圾邮件的本地,对吧?
更新:
如果main()看起来像这样:
int main() { spam(); foo(); }
然后调用堆栈应该是什么样子?
你的图纸不正确。 函数的本地堆栈变量都低于任何返回地址。 否则,正如您所观察到的,当您调用函数时,本地人会迷路。
它应该是这样的:
| parameters for foo() | | return address of foo() | | local of spam() | | local of spam() | | local of spam() | | parameters for spam() | | return address of spam() | | locals of main() | | parameters for main() |
我认为令人困惑的是,您认为变量声明被视为语句并按顺序执行。 实际上,编译器通常会分析一个函数来决定所有局部变量需要多少堆栈空间。 然后它会发出代码来相应地调整堆栈指针,并在进入函数时进行调整。 然后,对其他函数的任何调用都可以推入堆栈,而不会干扰此函数的堆栈帧。