提问者:小点点

为什么函数激活记录中需要动态链接?(静态作用域语言)


我读到动态链接指向以前的激活记录(又名“堆栈帧”),所以在动态范围编程语言中是有意义的。但是在静态范围编程语言中,为什么访问链接(指向一个较低嵌套级别的函数激活记录)是不够的?特别是在C中-为什么不需要访问链接?为什么需要动态链接?


共2个答案

匿名用户

我将使用我更熟悉的术语:

激活记录:堆栈框架

动态链接:[保存]帧指针

所以,我将您的问题解释为:为什么需要帧指针?[1]

不需要帧指针。

一些编译器(例如Green Hills C,GCC-O2)通常不生成一个,或者可以要求不生成它(MSVC,GCC)。

也就是说,它当然有它的好处:

>

  • 轻松遍历调用堆栈:生成堆栈跟踪就像遍历帧指针构成头部的链表一样简单。使实现堆栈跟踪和调试器变得更加容易。

    更容易的代码生成:可以通过索引帧指针而不是一直变化的堆栈指针来引用堆栈变量。堆栈指针随着每次push/pop的变化而变化,帧指针在函数内保持不变(在序言/尾声之间)

    如果出现问题,可以使用帧指针完成堆栈展开。这就是Borland的结构化异常处理(SEH)的工作方式。

    简化堆栈管理:特别是setjmp(3)alloca(3)和C99-VLA的实现可能(并且通常确实)依赖于它。

    缺点:

    • 寄存器用法:x86只有8个通用寄存器。其中一个需要完全专用于保存帧指针。
    • 开销:为每个函数生成序言/尾声。

    但是正如您所注意到的,编译器可以生成非常好的代码,而无需维护帧指针。

    [1]如果不是这个意思,请详细说明。

  • 匿名用户

    您的问题可能与GCC的-fomit-frame-poster优化选项有关,然后看这个。

    BTW,许多人在调用栈中用激活记录来命名调用帧。延续的概念,以及延续传递样式和正态形式是密切相关的。

    动态链接真的只对嵌套函数(也许还有闭包)有用,标准C没有。有人说显示链接。标准C没有嵌套函数,所以不需要任何相关的技巧(显示链接、蹦床、…)。

    GCC编译器提供嵌套函数作为C语言扩展,并通过激活记录上的动态链接实现它们,非常接近您正在考虑的内容。另请阅读关于男子或男孩测试和蹦床的维基页面。