为什么堆栈不会回滚

时间:2014-01-26 15:44:20

标签: c++ operating-system stack

我们研究过Stack的扩展和缩小。但在实践中它不会发生 举一个从地址100扩展到0的堆栈的例子,即第一个变量为100,然后是99等等。现在我们编写以下代码

int main()
{
   {
      int i;
      cout<<&i;//100 is displayed on screen
   }
   {
      int j;
      cout<<&j;//99 is displayed on screen
   }
}

现在,当我们宣布i时,它会转到地址100,然后它的范围结束。然后j在新范围中声明,现在它应该再次具有地址100,因为我已经完成并且堆栈应该回滚但是它没有,j具有地址99.为什么?你能解释一下吗?

3 个答案:

答案 0 :(得分:6)

标准没有对局部变量的存储做出这样的承诺。没有理由相信声明的顺序与它们在记忆中的排列顺序有任何关系。

完全按照编译器的要求完成它的工作。实际上,对于您的程序,编译器可以对两个变量使用相同的地址。我希望任何体面的优化编译器都可以这样做。

现在,在实践中,编译器可能会使用您所谈论的各种优化。但是,如何实现这些优化将因编译器而异。并且没有理由将您描述的简单规则普遍应用于所有函数。编译器可以为一个函数选择一个策略,为不同的函数选择不同的策略。编译器的行为可能会有所不同,具体取决于其选项。

当然,如果你在谈论与函数调用相关的堆栈帧,那么它就不同了。显然,当您进行新的函数调用时,会分配一个新的堆栈帧。然后当函数返回时,该堆栈帧被销毁,并且重新输入调用函数的堆栈帧。但这是一个完全不同的问题,而不是你在问题中讨论的内容。

答案 1 :(得分:5)

在堆栈上分配空间需要一些时间,尽管非常小。编译器进行的一个非常常见的优化是分析函数内声明的变量,并在函数开始的同时为所有变量保留堆栈空间。

更聪明的编译器会意识到两个变量的生命周期不重叠,让它们共享相同的位置。

答案 2 :(得分:0)

在函数调用的情况下,堆栈将始终展开并回滚,因为执行路径实际上不可预测,我们需要存储有关局部变量的信息,并在调用树中返回每个正在运行的函数的地址。

这里的情况不同,堆栈指针甚至没有移动,编译器可以自由地优化代码并为两个小变量使用两个不同的地址,即使这会导致最小的内存浪费。