使用 GOTO 时对 StackFrames 有何影响?

The*_*war 2 c memory stack operating-system function

我正在关注内存布局和堆栈以了解堆栈帧..

作者很好地解释了堆栈帧,并说明了在给定时间点堆栈中的内容

他也在下面问了一些问题

  • 假设一个程序进行了 5 次函数调用。堆栈上应该有多少帧?
  • 我们看到堆栈线性向下增长,当函数返回时,堆栈上的最后一帧被释放并返回到未使用的内存。是否有可能将堆栈中间某处的帧返回到未使用的内存中?如果是这样,那对正在运行的程序意味着什么?
  • goto() 语句可以导致堆栈中间的帧被释放吗?答案是否定的,但为什么呢?
  • longjmp() 会导致堆栈中间的帧被释放吗?

以下是我尝试回答上述问题

  • 假设一个程序进行了 5 次函数调用。堆栈上应该有多少帧?

如果函数相互独立,则只有主函数或主函数和调用函数会在堆栈中

我们看到堆栈线性向下增长,当函数返回时,堆栈上的最后一帧被释放并返回到未使用的内存。是否有可能将堆栈中间某处的帧返回到未使用的内存中?如果是这样,那对正在运行的程序意味着什么?

我认为这是不可能的,因为这可能会破坏内存

我不确定其余的问题。你能帮忙解决这个问题吗

如果您需要更多信息,请告诉我

gsa*_*ras 5

假设一个程序进行了 5 次函数调用。堆栈上应该有多少帧?

6、最多(假设在调用所有函数之前没有函数返回)。一对main(),一个用于每个函数调用。

我们看到堆栈线性向下增长,当函数返回时,堆栈上的最后一帧被释放并返回到未使用的内存。是否有可能将堆栈中间某处的帧返回到未使用的内存中?如果是这样,那对正在运行的程序意味着什么?

不,因为堆栈是一种不允许随机访问删除的。您只能从堆栈中弹出。

goto() 语句可以导致堆栈中间的帧被释放吗?答案是否定的,但为什么呢?

因为它会改变堆栈展开。使用 goto 退出代码块不会解开堆栈,这是您应该(几乎)永远不要使用 goto 的原因之一。阅读什么是堆栈展开?但是,请注意这是与 C++ 相关的,正如 Antti 提到的,在 C 中 goto out of block 是明确定义的。

longjmp() 会导致堆栈中间的帧被释放吗?

我想是的,因为这是一个空间案例。但这与我的第二个答案有点矛盾。

当通过 setjmp/longjmp 执行“非本地转到”时,不会发生正常的“堆栈展开”。因此,也不会发生任何所需的清理操作。

来自 C 的 longjmp() 函数(有关基础知识,请参阅setjmp.h的维基百科条目)。longjmp()沿着栈向下跳转到相应的 setjmp(),跨越与中间一样多的栈帧。与我们将看到的其他方法不同,longjmp()不会遍历帧列表,它只是一次全部爆炸,肆意无视它们可能包含的任何珍贵或美丽的东西。

在此处阅读更多相关信息。

longjmp()将堆栈返回到先前用 保存的状态setjmp()。如果中间的任何框架被删除,那么下面的所有框架也将被删除;即longjmp,正如 Klas 所提到的,在 a 之后堆栈中不会有“洞” 。