我读到动态链接指向以前的激活记录(又名“堆栈帧”),所以在动态范围编程语言中是有意义的。但是在静态范围编程语言中,为什么访问链接(指向一个较低嵌套级别的函数激活记录)是不够的?特别是在C中-为什么不需要访问链接?为什么需要动态链接?
我将使用我更熟悉的术语:
激活记录:堆栈框架
动态链接:[保存]帧指针
所以,我将您的问题解释为:为什么需要帧指针?[1]
不需要帧指针。
一些编译器(例如Green Hills C,GCC-O2)通常不生成一个,或者可以要求不生成它(MSVC,GCC)。
也就是说,它当然有它的好处:
>
轻松遍历调用堆栈:生成堆栈跟踪就像遍历帧指针构成头部的链表一样简单。使实现堆栈跟踪和调试器变得更加容易。
更容易的代码生成:可以通过索引帧指针而不是一直变化的堆栈指针来引用堆栈变量。堆栈指针随着每次push/pop的变化而变化,帧指针在函数内保持不变(在序言/尾声之间)
如果出现问题,可以使用帧指针完成堆栈展开。这就是Borland的结构化异常处理(SEH)的工作方式。
简化堆栈管理:特别是setjmp(3)
、alloca(3)
和C99-VLA的实现可能(并且通常确实)依赖于它。
缺点:
但是正如您所注意到的,编译器可以生成非常好的代码,而无需维护帧指针。
[1]如果不是这个意思,请详细说明。
您的问题可能与GCC的-fomit-frame-poster
优化选项有关,然后看这个。
BTW,许多人在调用栈中用激活记录来命名调用帧。延续的概念,以及延续传递样式和正态形式是密切相关的。
动态链接真的只对嵌套函数(也许还有闭包)有用,标准C没有。有人说显示链接。标准C没有嵌套函数,所以不需要任何相关的技巧(显示链接、蹦床、…)。
GCC编译器提供嵌套函数作为C语言扩展,并通过激活记录上的动态链接实现它们,非常接近您正在考虑的内容。另请阅读关于男子或男孩测试和蹦床的维基页面。