Delphi 関数では、結果が var-parameter として実装されることがよくあります(QC チケットにもかかわらず out-parameter ではありません)。
文字列定数は、基本的に負の refcounter を持つ変数であり、自動メモリの [割り当て解除] を抑制する必要があります。http://docwiki.embarcadero.com/RADStudio/XE3/en/Internal_Data_Formats#Long_String_Types
それは本当にそれを抑制します: 以下のコードはリークしません。
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;
しかし、操作変数を変更すると、すぐに大量のリークが始まります。
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;
string := const
LValue に応じて、さまざまな呼び出しで実装されていることがわかります。
- 結果: AnsiString -> LStrAsg
- 結果: UnicodeString: -> UStrAsg
- ローカル変数: UnicodeString: -> UStrLAsg
- ローカル変数: AnsiString: -> LStrLAsg
後者の 2 つは期待どおりにポインターを複製していますが、前の 2 つは、UniqueString
呼び出しを追加した場合のように、文字列を新しいインスタンスにコピーしています。
なぜその違い?