1

我正在使用 Delphi 2009 并使用以下代码段得到一些奇怪的错误:

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

我猜想当超出范围并且在某些时间条件下 DoSomething 会产生最奇怪的结果时,字符串会被破坏。所以第一个问题是:我说的对吗?

第二个问题是:如何规避被破坏的字符串?这样做的正确方法是什么?

提前致谢。

4

4 回答 4

7

所以第一个问题是:我说的对吗?

很可能,是的。Delphi 的 AnsiString 是引用计数的。当Str超出范围时,引用计数会减少。如果引用计数达到零,那么它占用的内存可能会被重用。

第二个问题是:如何规避被破坏的字符串?正确的方法是什么?

通过不使用指针,如下所示:

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 超出范围时,它会被破坏,并且 CharPtr 现在有指向一些随机垃圾的危险。

通过以下修改

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

一切似乎都很好。

于 2009-10-06T10:42:09.733 回答
0

为什么不按值传递字符串,而不是指针/引用?

于 2009-10-06T10:31:48.210 回答