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

Ast*_*oth 5 delphi

function Test: Boolean;
var
  a, b, c: Integer;
begin
  ...
end;
Run Code Online (Sandbox Code Playgroud)

当执行包含这样的代码的程序,是a,bc每个时间分配Test被调用时,或者是它们在执行的初始化阶段仅分配一次某处?我问这个是因为调试器中没有这样的信息.

Ign*_*ams 7

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

  • @Marco:它开启了一堆新鲜的蠕虫. (2认同)

Arn*_*hez 3

这是一个更准确的版本。

局部变量分配:

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

栈是如何分配的?

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

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

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

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

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

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

所有这些堆栈分配/初始化过程就是为什么对于一些小函数/方法来说,声明它们inline将使代码执行得更快:如果函数内的过程非常简单,所有这些堆栈处理有时会很慢。

更多详细信息请参见Delphi官方文档