2
var
  S: string;
begin
  SetLength(S, MAX_SIZE);// when casting to a PChar, be sure the string is not empty
  SetLength(S, GetModuleFilename(0, PChar(S), Length(S)));
  // statements
end;

バッファをコピーするオーバーヘッドを排除するために、文字列をPCharにキャストできます(ルーチンがメモリにPCharを残す必要がないことが確実な場合)。 http://docwiki.embarcadero.com/RADStudio/en/Passing_a_Local_Variable_as_a_PChar

文字列があり、参照カウントが0に減少するまでメモリに残るため、スコープの途中で削除されることはありません。では、なぜ私たちPCharは記憶にとどまる必要があるのでしょうか?PChar以前に別のAPI関数に渡されたものとまったく同じ参照を必要とするAPI関数はありますか?

特にサンプルコードを検討しています。したがって、質問は「ルーチンに渡されたPChar(文字列からの型キャスト)が戻った後もメモリに残る必要があるのはなぜですか?」である必要があります。非同期i/oルーチン、呼び出し元が戻った後に渡されたpcharにアクセスする非同期メソッド、または別のスレッドによるグローバル文字列の変更は、正当な理由です。

4

1 に答える 1

6

APIがポインタを後で保存する場合があります。たとえば、非同期IOについて考えてみます。

または、次のようなコードを記述した場合も失敗します。

function Broken():PChar;
var s:string;
begin
  s:=IntToStr(Random(100));//no string constant
  return PChar(s);
end;

重要な点の1つは、refcount> 1の文字列をにキャストするとPChar、コピーが作成され、refcount=1の文字列が渡されることです。したがってPChar、refcount> 1であっても、渡したsが無効になると無効になります。

別の壊れた例:

var p:PChar;
var s:string;

s := IntToStr(Random(100));//no string constant
p := PChar(s);
s := "ABC";
DoSomething(p);//p is invalid by now
于 2012-02-08T14:06:36.667 に答える