有关函数调用堆栈混乱 [英] confusion about function call stack

查看:227
本文介绍了有关函数调用堆栈混乱的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据维基:

呼叫者将返回地址压入堆栈,和被叫
  子程序,当它完成,弹出返回地址关闭呼叫
  栈和控制转移到该地址。

the caller pushes the return address onto the stack, and the called subroutine, when it finishes, pops the return address off the call stack and transfers control to that address.

产品图来自维基:

我不明白这一点。
说我有一个C程序如下:

I don't quite understand this. Say I have a C program as follows:

#include <stdio.h>

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;
}

和我想调用堆栈应该是这样一个图如下:

And I think the call stack should be something like a drawing as follows:

<None> means none local variables or params

      _| parameters for foo() <int x>  |_
top    | local of spam() <int c>       |
^      | return address of foo()       |<---foo() called, when finishes, return here?
|      | local of spam() <int b>       |
bot    | local of spam() <int a>       |
      _| parameters for spam() <None>  |_
       | locals of main() <None>       | 
       | return address of spam()      |<---spam() called, when finishes, return here?
       | parameters for main() <None>  |

问:

据引述维基的话,

被调用的子程序,当它完成,弹出返回地址关闭
  调用堆栈和控制转移到该地址。

the called subroutine, when it finishes, pops the return address off the call stack and transfers control to that address.

1.Is我的画吧?

2.如果是正确的,那么当富(1)完成后,它将

2.If it is right, then when foo() finishes, it will

弹出返回地址关闭调用堆栈和控制权转移到
  该地址

pop the return address off the call stack and transfer control to that address

,但怎么能突然关闭返回地址?
  因为当foo的结束,当前堆栈指针指向垃圾邮件的地方,
  对吧?

, but how can it pop off the return address? Because when foo finishes, the current stack pointer is pointing to spam's local , right?

更新:

如果在main()看起来是这样的:

what if the main() looks like this:

int main()
{ 
    spam();
    foo();
}

然后调用堆栈应该是什么样子?

then what the call stack should look like?

推荐答案

您的绘图是不正确的。一个函数的局部堆栈变量均低于任何回报的地址。否则,你的观察,当地人会得到当你调用一个函数丢失。

Your drawing is not correct. The local stack variables for a function are all below any return addresses. Otherwise, as you have observed, the locals would get lost when you call a function.

这应该是这样的:

| parameters for foo() <int x>  |
| return address of foo()       |
| local of spam() <int c>       |
| local of spam() <int b>       |
| local of spam() <int a>       |
| parameters for spam() <None>  |
| return address of spam()      |
| locals of main() <None>       | 
| parameters for main() <None>  |

我觉得困惑的是,您认为变量声明被视为报表和按顺序执行。事实上,编译器通常会分析功能来决定多少堆栈空间是需要所有的局部变量。然后,它会发出code相应调整堆栈指针和调整在进入功能的。然后其他的功能的任何电话可以压入栈,而不具有这种功能的堆栈帧的干扰。

I think the confusion is that you believe that variable declarations are treated as statements and executed in order. In fact the compiler will typically analyse a function to decide how much stack space is needed for all the local variables. Then it emits code to adjust the stack pointer accordingly and that adjustment is made on entry to the function. Any calls to other functions can then push onto the stack without interfering with this function's stack frame.

这篇关于有关函数调用堆栈混乱的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆