关于函数调用堆栈的混淆

根据维基:

调用者将返回地址压入堆栈,被调用的子例程一旦完成,就会从调用堆栈中弹出返回地址并将控制转移到该地址。

来自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()  | 

我认为令人困惑的是,您认为变量声明被视为语句并按顺序执行。 实际上,编译器通常会分析一个函数来决定所有局部变量需要多少堆栈空间。 然后它会发出代码来相应地调整堆栈指针,并在进入函数时进行调整。 然后,对其他函数的任何调用都可以推入堆栈,而不会干扰此函数的堆栈帧。