いいえ、私はそんなことは起こり得ないと思います。文字列変数は期待していない値を取得する可能性がありますが、メモリがリークすることはありません。このことを考えてみましょう:
ここ
var
Global: string;
procedure One(const Arg: string);
begin
Global := '';
// Oops. This is an invalid reference now. Arg points to
// what Global used to refer to, which isn't there anymore.
writeln(Arg);
end;
procedure Two;
begin
Global := 'foo';
UniqueString(Global);
One(Global);
Assert(Global = 'foo', 'Uh-oh. The argument isn''t really const?');
end;
One
の引数はそうおそらく、constとして宣言され、それは変更されません。しかし、One
は、仮パラメータの代わりに実際のパラメータを変更することで回避します。プロシージャTwo
は、One
の引数がconstであることを "知っている"ので、実際のパラメータが元の値を保持することを期待しています。アサーションは失敗します。
文字列はリークしませんでしたが、このコードでは、ダングリングリファレンスを文字列として取得する方法を示しています。 Arg
は、ローカル別名Global
です。 Global
を変更しましたが、Arg
の値は変更されず、constとして宣言されているため、関数への入力時に文字列の参照カウントがインクリメントされませんでした。再割り当てGlobal
は、参照カウントをゼロに落とし、その文字列は破棄されました。 varとしてArg
を宣言すると同じ問題が発生します。値を渡すことでこの問題が解決されます。 (UniqueString
への呼び出しは、文字列が参照カウントされていることを確認するだけです。そうでなければ、参照カウントされていない文字列リテラルである可能性があります)。シンプルなタイプは免疫です。
文字列をリークする唯一の方法は、文字列以外のものとして扱うか、非型対応のメモリ管理機能を使用することです。Mghie's answerには、FillChar
を使用して文字列以外の文字列として文字列を処理する方法が記載されています。非タイプ認識メモリ機能には、GetMem
およびFreeMem
が含まれます。例:
type
PRec = ^TRec;
TRec = record
field: string;
end;
var
Rec: PRec;
begin
GetMem(Rec, SizeOf(Rec^));
// Oops. Rec^ is uninitialized. This assignment isn't safe.
Rec^.field := IntToStr(4);
// Even if the assignment were OK, FreeMem would leak the string.
FreeMem(Rec);
end;
2つの方法で修正できます。一つはInitialize
とFinalize
を呼び出すことです:
GetMem(Rec, SizeOf(Rec^));
Initialize(Rec^);
Rec^.field := IntToStr(4);
Finalize(Rec^);
FreeMem(Rec);
他のタイプの認識機能を使用することです:
New(Rec);
Rec^.field := IntToStr(4);
Dispose(Rec);
私は思っていたように見えますが、2009年にはAVではありません。私はあなたが言っていたことを信じています。 –
$ STRINGCHECKSがONの場合、Delphi 2009では "const"の機能が失われるため、AVはありません。 –