何时为局部变量分配空间?

时间:2010-12-21 05:15:00

标签: delphi

实施例

function Test: Boolean;
var
  a, b, c: Integer;
begin
  ...
end;

当执行包含此类代码的程序时,每次调用a时都会分配bcTest,或者它们只在某处分配一次执行的初始化阶段?我问这个是因为调试器中没有这样的信息。

2 个答案:

答案 0 :(得分:7)

在调用函数后,在堆栈中创建局部变量。默认情况下,当函数返回时,被调用的函数将删除它们。

答案 1 :(得分:3)

这是一个更精确的版本。

分配了局部变量:

  • 通常在堆栈上;
  • 在寄存器中,如果优化器可以使用它:例如,只有一个循环和var i: integer声明为局部变量的简单方法可能会将i分配为CPU寄存器,以获得更好的速度。

如何分配堆栈?

在x86和x64方案上,编译器具有相同的过程:

  • 它首先在编译时计算所需的所有空间;
  • 它生成代码以在堆栈上保留此空间(例如MOV EBP,ESP; SUB ESP,16);
  • 它生成用于初始化在堆栈上分配的引用计数变量的代码(例如string) - 其他类型的变量(如integer)没有默认值,并且可以是任何随机内容在堆栈上;
  • 如果存在一些引用计数变量,它会生成隐藏的try..finally块;
  • 它为函数/方法的内部生成代码;
  • 现在这里是函数/方法的finally部分:它生成代码以释放所有引用计数变量;
  • 它生成代码以释放堆栈上的空间(例如MOV ESP,EBP);
  • 它生成返回调用函数的代码。

大多数情况下,会创建一个“堆栈帧”(由寄存器EBP指向):它用于直接访问堆栈上分配的所有变量。

函数的result变量有一个特定的处理:有时,它是一个CPU / FPU寄存器,有时,它是由调用者初始化的变量,并作为附加参数传递。

在x64上,它有点复杂,因为异常处理不相同,并且如果存在内部调用,则所有寄存器都需要在堆栈上分配一些空间。

在Mac OS上,存在一些对齐问题。

所有这些堆栈分配/初始化过程是一些小函数/方法的原因,声明它们inline将使代码执行更快:所有这些堆栈处理有时很慢,如果函数内的进程非常简单。

more details, see the official Delphi documentation