1

Delphi 2009を使用していますが、次のコードセグメントを使用すると奇妙なエラーが発生します。

var
  Str     : AnsiString;
  CharPtr : PAnsiChar;
...
CharPtr := PAnsiChar (Str);
ExecuteInBackgroundThread (
  procedure
  begin
  DoSomething (CharPtr);
  end);

スコープから外れると文字列が破壊され、タイミング条件によってはDoSomethingが最も奇妙な結果をもたらすと推測しています。したがって、最初の質問は次のとおりです。私は正しいですか?

2番目の質問は次のとおりです。破壊されている文字列を回避するにはどうすればよいですか?これを行うための適切な方法は何ですか?

前もって感謝します。

4

4 に答える 4

7

したがって、最初の質問は次のとおりです。私は正しいですか?

おそらくそうです。DelphiのAnsiStringは参照カウントされます。スコープ外にStrなると、参照カウントがデクリメントされます。参照カウントがゼロに達すると、それが占有していたメモリが再利用される可能性があります。

2番目の質問は次のとおりです。破壊されている文字列を回避するにはどうすればよいですか?これへの適切な方法は何ですか?

次のように、ポインタを使用しないことによって:

var
  Str     : AnsiString;
...
ExecuteInBackgroundThread (
  procedure
  begin
  DoSomething (Str);
  end);
于 2009-10-06T10:52:35.743 に答える
4

使用するだけです:

DoSomething(PAnsiChar(Str));

一般的なルールは単純です。最後の瞬間までPCharを使用しないでください。このようにして、メモリ管理の問題についてあまり考える必要はありません(ほとんどの場合)。

このすばらしい記事も参照してください。

于 2009-10-06T11:37:29.000 に答える
2

さて、私はそれを理解したかもしれないと思います。

匿名メソッドを使用しているので、コンパイラはローカル変数をキャプチャする必要があります。どうやら、それは私が匿名メソッドで実際に使用する変数のみをキャプチャします。つまり、CharPtrはキャプチャされますが、SendStrはキャプチャされません。したがって、SendStrがスコープから外れると、SendStrは破棄され、CharPtrはランダムなガベージを指す危険にさらされます。

以下の変更で

ExecuteInBackgroundThread (
  procedure
  begin
  Log (Str);
  DoSomething (CharPtr);
  end);

すべてが正常に機能しているようです。

于 2009-10-06T10:42:09.733 に答える
0

ポインタ/参照ではなく、値で文字列を渡してみませんか?

于 2009-10-06T10:31:48.210 に答える