const记录参数是否放在堆栈中?

时间:2018-01-09 02:20:58

标签: delphi stack

假设我有一个名为TSomeRec的记录类型:

type
  TSomeRec = record
    // ...
  end;

...以及一个带有const TSomeRec参数的过程:

procedure SomeProc(const someRec: TSomeRec);
begin
  // ...
end;

调用SomeProc时,const someRec参数是作为值还是作为引用传递给堆栈的?

我问的原因是,在我正在处理的代码中,有问题的记录类型包含一个大规模的静态数组,因此是巨大的。 (不,我无法改变它。)我很担心将这么大的记录放在堆栈上,我认为const可能有所帮助。这个代码溢出堆栈时遇到了问题,当发生这种情况时,我只会遇到神秘的访问冲突而不是任何堆栈溢出错误。

1 个答案:

答案 0 :(得分:9)

这取决于。这实际上是在在线帮助中描述的,但现在就是这样。

在32位Windows可执行文件中(即使用WIN32定义编译的代码),如果记录不大于32位寄存器,则按原样推送到堆栈,即按值传递 。如果记录大于寄存器,则传递指向记录的指针,即通过引用传递。这是默认的register调用约定。对于其他平台或调用约定可能有所不同,但上述情况很可能是一般情况。

DocWiki

  

常量参数可以通过值或引用传递给函数,具体取决于所使用的特定编译器。要强制编译器通过引用传递常量参数,可以将[Ref]装饰器与const关键字一起使用。

But see the Delphi Language Guide too。它描述了如何传递所有类型的参数,例如

  

将1,2或4个字节的集合,记录和静态数组作为8位,16位和32位值传递。较大的集合,记录和静态数组作为32位指针传递给该值。此规则的一个例外是记录总是直接在cdecl,stdcall和safecall约定下的堆栈上传递;以这种方式传递的记录的大小向上舍入到最近的双字边界。

但是,对于较新的编译器而言已经发生了变化。

但可以肯定的是,您可以随时查阅CPU视图。在那里你可以看到会发生什么。