调用栈的英文叫做call stack,从其英文书名来看,知道它本身就是一个栈,故而它满足栈的先入后出的特性。

wiki上有篇文章讲述call stack:http://en.wikipedia.org/wiki/Call_stack

关于栈的溢出(stack overflow),有下面的定义:

Since the call stack is organized as a stack, 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. If a called subroutine calls on to yet another subroutine, it will push another return address onto the call stack, and so on, with the information stacking up and unstacking as the program dictates. If the pushing consumes all of the space allocated for the call stack, an error called a stack overflow occurs, generally causing the program to crash.

关于call stack的作用,它也谈到了:

Storing the return address When a subroutine is called, the location (address) of the instruction at which it can later resume needs to be saved somewhere. Using a stack to save the return address has important advantages over alternatives. One is that each task has its own stack, and thus the subroutine can be reentrant, that is, can be active simultaneously for different tasks doing different things. Another benefit is that recursion is automatically supported. When a function calls itself recursively, a return address needs to be stored for each activation of the function so that it can later be used to return from the function activation. This capability is automatic with a stack.

存储指令的返回地址,是call stack最重要的作用,简单,而且会带来很多其它的好处,譬如每个线程维护自己的调用栈,还有递归调用。

Local data storage A subroutine frequently needs memory space for storing the values of local variables, the variables that are known only within the active subroutine and do not retain values after it returns. It is often convenient to allocate space for this use by simply moving the top of the stack by enough to provide the space. This is very fast compared to heap allocation. Note that each separate activation of a subroutine gets its own separate space in the stack for locals.

局部数据存储在栈这样的存储空间中,比堆存储要快得多,原因在于,只需要简单的移动栈顶的位置就可以了,当需要分配栈空间时。

Parameter passing Subroutines often require that values for parameters be supplied to them by the code which calls them, and it is not uncommon that space for these parameters may be laid out in the call stack. Generally if there are only a few small parameters, processor registers will be used to pass the values, but if there are more parameters than can be handled this way, memory space will be needed. The call stack works well as a place for these parameters, especially since each call to a subroutine, which will have differing values for parameters, will be given separate space on the call stack for those values.

调用栈还可以用来传递调用函数的参数,通常是在参数较多的时候。

Pointer to current instance Some object-oriented languages (e.g., C++), store the this pointer along with function arguments in the call stack when invoking methods. The this pointer points to the object instance associated with the method to be invoked.

它还可以用来传递C++中的this指针。

Enclosing subroutine context Some programming languages (e.g., Pascal and Ada) support nested subroutines, allowing an inner routine to access the context of its outer enclosing routine, i.e., the parameters and local variables within the scope of the outer routine. Such static nesting can repeat - a function declared within a function declared within a function... The implementation must provide a means by which a called function at any given static nesting level can reference the enclosing frame at each enclosing nesting level. Commonly this reference is implemented by a pointer to the encompassing frame, called a "downstack link" or "static link", to distinguish it from the "dynamic link" that refers to the immediate caller (which need not be the static parent function). For example, languages often allow inner routines to call themselves recursively, resulting in multiple call frames for the inner routine's invocations, all of whose static links point to the same outer routine context. Instead of a static link, the references to the enclosing static frames may be collected into an array of pointers known as adisplay which is indexed to locate a desired frame. The Burroughs B6500 had such a display in hardware that supported up to 32 levels of static nesting.

用来解决一些语言支持的闭包特性。

处理以上的作用外,文章还谈到了其它一些作用。

关于call stack的具体结构布局,不同的平台系统有不同的实现:

一个call stack通常由一个或多个栈帧(stack frames)组成,假如一个函数DrawLine正在被另外一个函数DrawSquare调用,这时候的call stack可以表示如下:

这里栈顶向上(高地址)增长,不同的硬件平台有不同的实现。

The stack frame at the top of the stack is for the currently executing routine. The stack frame usually includes at least the following items (in push order):

  • the arguments (parameter values) passed to the routine (if any);
  • the return address back to the routine's caller (e.g. in the DrawLine stack frame, an address into DrawSquare's code); and
  • space for the local variables of the routine (if any).

The stack and frame pointers

The data stored in the stack frame may sometimes be accessed directly via the stack pointer register (SP, which indicates the current top of the stack). However, as the stack pointer is variable during the activation of the routine, memory locations within the stack frame are more typically accessed via a separate register which makes relative addressing simpler and also enables dynamic allocation mechanisms (see below). This register is often termed the frame pointer or stack base pointer (BP) and is set up at procedure entry to point to a fixed location in the frame structure (such as the return address).

Stack frame sizes

As different routines have different parameters and local data, stack frames have varying sizes. Although they may often be fixed across all activations of a particular routine, many modern languages also support dynamicallocations on the stack, which means that the local data area will vary from activation to activation with a size that may be unspecified when the program is compiled. In this case, access via a frame pointer, rather than via the stack pointer, is usually necessary since the offsets from the stack top to values such as the return address would not be known at compile time. If the subroutine does not use dynamic stack allocation and does not call any further subroutines, the frame pointer is not needed, and the register may be used for other purposes.

Storing the address to the caller's frame

In most systems a stack frame has a field to contain the previous value of the frame pointer register, the value it had while the caller was executing. For example, the stack frame of DrawLine would have a memory location holding the frame pointer value that DrawSquare uses (not shown in the diagram above). The value is saved upon entry to the subroutine and restored upon return. Having such a field in a known location in the stack frame enables code to access each frame successively underneath the currently executing routine's frame, and also allows the routine to easily restore the frame pointer to the caller's frame, just before it returns.

Lexically nested routines

Further information: Nested function and Non-local variable

Programming languages that support nested subroutines also have a field in the call frame that points to the stack frame of the latest activation of the procedure that most closely encapsulates the callee, i.e. the immediatescope of the callee. This is called an access link or static link (as it keeps track of static nesting during dynamic and recursive calls) and provides the routine (as well as any other routines it may invoke) access to the local data of its encapsulating routines at every nesting level. Some architectures, compilers, or optimization cases store one link for each enclosing level (not just the immediately enclosing), so that deeply nested routines that access shallow data do not have to traverse several links; this strategy is often called a display.[1] Access link(s) can be optimized away in cases where an inner function does not access any (non constant) local data in the encapsulation—pure functions, i.e. routines communicating via argument(s) and return value(s) only would be an example of this. Some historical computers, such as the Burroughs large systems, had special "display registers" to support nested functions while compilers for most modern machines (such as the ubiquitous x86) simply reserve a few words on the stack for the pointers, as needed.

Overlap

For some purposes, the stack frame of a subroutine and that of its caller can be considered to overlap, the overlap consisting of the area where the parameters are passed from the caller to the callee. In some environments, the caller pushes each argument onto the stack, thus extending its stack frame, then invokes the callee. In other environments, the caller has a preallocated area at the top of its stack frame to hold the arguments it supplies to other subroutines it calls. This area is sometimes termed the outgoing arguments area or callout area. Under this approach, the size of the area is calculated by the compiler to be the largest needed by any called subroutine.

转载于:https://www.cnblogs.com/zerolee/archive/2012/06/17/2552760.html

调用栈(call stack)相关推荐

  1. 【译】理解Javascript函数执行—调用栈、事件循环、任务等

    原文作者:Gaurav Pandvia 原文链接:medium.com/@gaurav.pan- 文中部分链接可能需要梯子. 欢迎批评指正. 现如今,web开发者(我们更喜欢被叫做前端工程师)用一门脚 ...

  2. Java异常的栈轨迹(Stack Trace)

    捕获到异常时,往往需要进行一些处理.比较简单直接的方式就是打印异常栈轨迹Stack Trace.说起栈轨迹,可能很多人和我一样,第一反应就是printStackTrace()方法.其实除了这个方法,还 ...

  3. 你不知道的JavaScript错误和调用栈常识

    大多数工程师可能并没留意过 JS 中错误对象.错误堆栈的细节,即使他们每天的日常工作会面临不少的报错,部分同学甚至在 console 的错误面前一脸懵逼,不知道从何开始排查,如果你对本文讲解的内容有系 ...

  4. 【备忘】visual studio调试状态下显示lua调用栈

    编辑文件:[VS安装目录]/Common7/Packages/Debugger/autoexp.dat,在文件最后[hresult]之上的空白插入以下代码,就可以在 visual studio调试的时 ...

  5. 【编程】堆(heap)和栈(stack)的区别

    从C/C++的内存分配(与操作系统相关)上来说,堆(heap),栈(stack)属于内存空间的一段区域. 效率: 栈是机器系统提供的数据结构,计算机会在底层对栈提供支持(有专门的寄存器存放栈的地址,压 ...

  6. 数据结构与算法 / 栈(stack)

    @time 2019-07-24 @author Ruo_Xiao @reference 极客时间 -> 数据结构与算法之美 ---------------------------------- ...

  7. php 打印函数调用栈,利用backtrace和backtrace_symbols函数打印调用栈信息

    本帖最后由 kylin_try 于 2017-2-6 08:41 编辑 在头文件"execinfo.h"中声明了三个函数用于获取当前线程的函数调用堆栈. #include int ...

  8. JVM之Java栈Java stack

    JVM之Java栈Java stack 目录: JVM体系结构概览 JVM之Java栈解析 1. JVM体系结构概览 2. JVM之Java栈解析 stack图 先简单认识,图示在一个栈中有两个栈帧: ...

  9. 使用Backtrace函数打印调用栈 - Debug居家必备

    glibc提供了backtrace这个库函数,可以用来打印call stack.比如我们可以在程序中注册常见的一些signal,比如SIGSEGMENT, SIGPIPE,然后在这些信号的回调函数中, ...

  10. 线程的属性 —— 分离的状态(detached state)、栈地址(stack address)、栈大小(stack size)

    参考:(四十二)线程--线程属性 作者:FadeFarAway 发布时间:2017-01-17 14:09:55 网址:https://blog.csdn.net/FadeFarAway/articl ...

最新文章

  1. 用koa mongodb 做了个简单的博客系统
  2. jcmd,大约JDK 11
  3. python 通过pip安装库 pycharm里面使用第三方库
  4. 假如我拥有字节工牌。。。
  5. Linux开发商计划停止开发32位版本
  6. 伦巴时间步的动作要领_拉丁舞教学视频,拉丁伦巴舞基本动作
  7. php like %%,thinkphp实现like模糊查询实例
  8. 如何在Android中设置铃声+震动
  9. Oracle IO问题解析(一)
  10. lr并发量和迭代的区别
  11. unity3d之计算两向量的旋转角
  12. ERROR 999999: Error executing function. The table name is invalid. Failed to execute (Reclassify).
  13. python opencv颜色通道_【Python+OpenCV之五】 分离颜色通道多通道图像混合
  14. php获得当前时间差,PHP获取当前时间差8小时的问题
  15. 撩妹攻略话术恋爱小程序源码分享
  16. 100个python算法超详细讲解:最佳存款方案
  17. Camunda入门(四) - 流程应用(支付流程)入门示例
  18. HDU6124 Euler theorem
  19. awk,gawk调用shell,bash中的变量 笔记221106
  20. RHCE-Day10-Apache

热门文章

  1. win10多合一原版系统_微软Win10专业版制作多合一系统安装盘教程
  2. python车辆型号识别_汽车型号和款式的识别 如何通过车架号来识别车的型号款式?查汽车型号...
  3. MATLAB 和 Python 建模和仿真
  4. MySQL 数值拼接字符串
  5. 电脑桌面天气计算机备忘录,有什么桌面软件可以显示:时间,天气,还有备忘录的?...
  6. 杨辉三角形Python实现
  7. C/C++——黑客数字雨特效
  8. Linux打开终端命令
  9. 外螺纹对照表_最新英制螺纹对照表(2016年完整版).
  10. 电影数据集TMDB数据分析练习