In Delphi function result is frequently implemented as var-parameter (not out-parameter despite QC ticket).
String constants are basically variables with negative refcounter, which should suppress automatic memory [de]allocation. http://docwiki.embarcadero.com/RADStudio/XE3/en/Internal_Data_Formats#Long_String_Types
It really does suppress it: the code below does not leak.
type
TDealRecord = record
id_Type: Integer;
Price: extended;
Remark: String;
end;
const const_loop = 100000000;
function TestVar: TDealRecord;
//procedure TestVar;
var
Li: Integer;
LRec: TDealRecord;
begin
for Li := 1 to const_loop do begin
FillChar(Lrec,SizeOf(LRec), 0);
LRec.Remark := 'Test';
// FillChar(Result,SizeOf(Result), 0);
// Result.Remark := 'Test';
end;
end;
But change the manipulated variable - and it immediately starts to leak heavily.
function TestVar: TDealRecord;
//procedure TestVar;
var
Li: Integer;
LRec: TDealRecord;
begin
for Li := 1 to const_loop do begin
// FillChar(Lrec,SizeOf(LRec), 0);
// LRec.Remark := 'Test';
FillChar(Result,SizeOf(Result), 0);
Result.Remark := 'Test';
end;
end;
It turns out that string := const
is implemented with different calls, depending on LValue:
- Result: AnsiString -> LStrAsg
- Result: UnicodeString: -> UStrAsg
- Local var: UnicodeString: -> UStrLAsg
- Local var: AnsiString: -> LStrLAsg
And while the latter two are cloning pointer as expected, the former two are copying the string to new instance, like if i add UniqueString
call to them.
Why that difference ?