为什么功能激活记录需要动态链接? (用静态范围的语言)

时间:2016-02-22 09:37:30

标签: c programming-languages

我读到动态链接指向上一个激活记录,因此在动态范围编程语言中是有意义的。但是在静态范围编程语言中,为什么访问链接(指向一个较低嵌套级别的功能的激活记录)是不够的? 特别是在C中 - 为什么不需要访问链接?为什么需要动态链接?

2 个答案:

答案 0 :(得分:4)

我将使用这个对我来说比较熟悉的命名法:

  

激活记录:堆叠框架

     

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

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

帧指针是必需的。

有些编译器(例如Green Hills C ++,带-O2的GCC)通常不会生成一个或者可能被要求不生成它(MSVC,GCC)。

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

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

  • 更容易生成代码:可以通过索引帧指针而不是随时更改堆栈指针来引用堆栈变量。堆栈指针随每次按下/弹出而变化,帧指针在函数内保持不变(在prologue/epilogue之间)

  • 如果出现问题,可以使用帧指针完成 stack unwinding 。这就是Borland的结构化异常处理(SEH)的工作原理。

  • 简化堆栈管理:特别是setjmp(3)alloca(3)C99-VLA的实现可能(通常也是如此)依赖于它。

缺点:

  • 注册用法:x86只有8个通用寄存器。其中一个需要专门用于保持帧指针。
  • 开销:为每个功能生成序言/结尾。

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

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

答案 1 :(得分:2)

您的问题可能与optimizing option-fomit-frame-pointer GCC有关,请参阅this

顺便说一下,很多人都在命名呼叫帧(在call stack中)你所说的激活记录continuation以及continuation passing styleA-normal form的概念密切相关。

动态链接实际上仅对nested函数(可能是closures)有用,而标准C没有它们。有些人会谈到 display 链接。标准C没有嵌套函数,所以不需要任何相关技巧(显示链接,蹦床......)。

GCC编译器提供nested functions作为 C语言扩展,并使用激活记录上的动态链接实现它们,非常接近您的想法。另请阅读man or boy testtrampoline上的wikipages。