什么是C和C ++上下文中的激活记录?
对于C / C ++程序员来说,它是什么意思以及了解它有多重要?
它在整个平台上是否相同,至少在概念上是这样?
我把它理解为用于通过函数存储局部变量的已分配内存块…
我想了解更多
激活记录是Stack Frame的另一个名称。 它是组成调用堆栈的数据结构。 它通常由以下部分组成:
- 被叫者的当地人
- 将地址返回给调用者
- 被调用者的参数
因此,调用堆栈由任意数量的激活记录组成,这些激活记录在添加新的子例程时被添加到堆栈中,并在它们返回时从堆栈中移除(通常)。
元素的实际结构和顺序是平台甚至实现定义。
对于C / C ++程序员,这种结构的一般知识对于理解某些实现function(如调用约定)以及为什么缓冲区溢出允许运行第三方恶意代码很有用。
更加亲密的知识将进一步推动上述概念,并允许程序员调试其应用程序并读取内存转储,即使没有调试器或调试符号也是如此。
更一般地说,一个C / C ++程序员可以通过他们的业余爱好者编程生涯的很大一部分,甚至没有考虑调用堆栈。
激活记录不是一个在谈论C或C ++语言本身时使用的概念。 激活记录的格式非常具体。
从概念上讲,参数的传递方式,局部变量的生命周期,函数返回的位置以及调用堆栈如何响应推测投掷都是C ++的重要组成部分(后者除外)。 这些实现方式的细节将影响特定平台的激活记录 ,但在C ++或C中编写代码通常不需要了解这一点。
当我们调用函数时,我们需要一个地方来存储调用者和被调用者的上下文,这个地方叫做激活记录 (AKA stack frame )。
是的, 激活记录组成了调用堆栈 ,但这并不意味着激活记录必须基于堆栈。 它是特定于实现的 。
你可能想知道“任何例子?”。
- 当然,只需看看IBM大型机的无堆栈 设计 , 堆栈不可用,其激活记录是基于堆的 。
- 相反,还有一个平台不提供堆 (AKA无堆 ),例如Arduino (但它也意味着不能使用新关键字和new-expression )。
- 除了硬件限制外,一些函数式语言不能在堆栈上存储局部变量 ,因此它们的激活记录在堆上分配,如果你想知道原因, 这里是一个很好的参考。
就像@FrakHB所说的那样,不仅堆和堆栈 ,其他内存区域也可以是激活记录 ,这就是具体的实现方式。
激活记录包含以下三件事
1.function定义
2.可变定义
3.function应用(函数调用)