Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are const record arguments put on the stack?

Tags:

stack

delphi

Suppose I have a record type called TSomeRec:

type
  TSomeRec = record
    // ...
  end;

... and a procedure that takes a const TSomeRec argument:

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

When SomeProc is called, will the const someRec argument be passed on the stack as a value or as a reference?

The reason I ask is that in the code I am working on, the record type in question contains a massive static array and so is huge. (No, I cannot change that.) I am nervous about putting such a large record on the stack, and I thought that const might help. I have had problems with this code with overflowing the stack, and when that happens, I just get mysterious access violations rather than any sort of stack overflow error.

like image 426
dan-gph Avatar asked Jan 09 '18 02:01

dan-gph


1 Answers

It depends. This is actually described in the online help, but here goes.

In 32 bit Windows executables (i.e. code compiled with WIN32 defined), if the record is not larger than a 32 bit register, it is pushed on the stack as-is, i.e. passed by value. If the record is larger than a register, a pointer to the record is passed, i.e. passed by reference. That is for the default register calling convention. It may be different for other platforms or calling conventions, but the above is very likely the general case.

DocWiki:

Constant parameters may be passed to the function by value or by reference, depending on the specific compiler used. To force the compiler to pass a constant parameter by reference, you can use the [Ref] decorator with the const keyword.

But see the Delphi Language Guide too. It describes how all kinds of parameters are passed, e.g.

Sets, records, and static arrays of 1, 2, or 4 bytes are passed as 8-bit, 16-bit, and 32bit values. Larger sets, records, and static arrays are passed as 32-bit pointers to the value. An exception to this rule is that records are always passed directly on the stack under the cdecl, stdcall, and safecall conventions; the size of a record passed this way is rounded upward to the nearest double-word boundary.

That has changed for newer compilers, though.

But to be sure, you can always consult the CPU view. There you can see what happens.

like image 72
Rudy Velthuis Avatar answered Sep 21 '22 17:09

Rudy Velthuis