编译器如何在堆栈上安排局部变量?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器如何在堆栈上安排局部变量?相关的知识,希望对你有一定的参考价值。

我们知道,局部变量位于堆栈上。但是,他们的订单是什么?它们是按照声明的顺序排列的吗?这意味着第一个声明的变量排列在堆栈的较高地址上(堆栈增长到较低的地址)?举个例子:

void foo(){
 int iArray[4];
 int iVar;
}

在堆栈上,局部变量 - iArrayiVar排列如下?

答案

最简单的实现使得很容易预测各种变量最终会在堆栈中出现的位置。但是,这些实现还允许某些安全问题(主要是溢出缓冲区并预测额外数据将覆盖的内容,允许注入shellcode)。

由于堆栈的布局是在大多数基于堆栈的语言中定义的实现(从技术上讲,许多这样的语言不强制使用堆栈,而是具有易于使用堆栈实现的语义),编译器编写者已经去过很长的make it hard to predict the stack layout at runtime

另一答案

只有关闭了优化!

一旦优化器获得您的代码,所有投注都将被取消。积极优化的常见策略是:

  • 如果变量从未使用过,则删除该变量,或者只是另一个变量的副本。
  • 按照使用顺序对变量重新排序。如果您的应用使用交换空间并且还有助于缓存利用率(在某些计算机上),这将极大地帮助您。
  • 将常用变量移动到寄存器中。常见的风险机器有32个可爱的通用寄存器。英特尔的八个单用途寄存器并不常见。
  • 更改数据类型。例如将小整数转换为整数通常会加快寄存器加载和缓存。
  • 重新排序存储以最小化松弛字节。例如char a,double b,char c,int d可以重新排序为double b,int d,char a,char c,从而节省10个字节。
另一答案

没有你可以依赖的规则。除非您开始优化代码,否则大多数编译器都将使用声明顺序。

启用优化可以导致重用堆栈空间,重新排序局部变量,甚至将变量移动到CPU寄存器,因此它们不再显示在堆栈上。

[编辑]在某些系统上,堆栈会增长到更大的地址。所以它从0x1000开始,下一个地址是0x1001,而不是从0xffff开始,下一个地址是0xfffe。

以上是关于编译器如何在堆栈上安排局部变量?的主要内容,如果未能解决你的问题,请参考以下文章

为啥要为局部变量保留堆栈空间?

堆栈动态和堆栈动态数组

C/C++程序中全局变量局部变量堆栈的存储区域介绍

如何从 Delphi 程序或编译器生成的调试信息中提取局部变量信息(地址和类型)?

如何从堆栈中访问函数局部变量?

使用 scanf 进入全局或局部变量(在堆栈上),32 位调用约定