琴弦过早损坏以及如何避免?

发布于 2024-08-07 07:01:48 字数 361 浏览 4 评论 0原文

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

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

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

第二个问题是:如何避免字符串被破坏?执行此操作的正确方法是什么?

提前致谢。

I'm using Delphi 2009 and get some strange errors using the following code segment:

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

I'm guessing that the string is destructed when falling out of scope and under some timing conditions DoSomething will yield the strangest results. So the first question is: am I right?

Second question is: How can I circumvent the string being destructed? What's the proper way to do this?

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

枯叶蝶 2024-08-14 07:01:48

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

最有可能的是,是的。 Delphi 的 AnsiString 是引用计数的。当 Str 超出范围时,引用计数就会递减。如果引用计数达到零,则它占用的内存可以被重用。

第二个问题是:我怎样才能
绕过字符串
被破坏了?正确的方法是什么
到这个?

不使用指针,如下所示:

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

So the first question is: am I right?

Most likely, yes. Delphi's AnsiString is reference counted. When Str goes out of scope, the reference count is decremented. If the reference count reaches zero then the memory it occupied may be reused.

Second question is: How can I
circumvent the string being
destructed? What's the proper way to
to this?

By not using pointers, like this:

var
  Str     : AnsiString;
...
ExecuteInBackgroundThread (
  procedure
  begin
  DoSomething (Str);
  end);
逆光飞翔i 2024-08-14 07:01:48

只需使用:

DoSomething(PAnsiChar(Str));

一般规则很简单:直到最后一刻才使用 PChar。这样您就不需要过多考虑内存管理问题(嗯,主要是)。

另请参阅这篇精彩文章

Just use:

DoSomething(PAnsiChar(Str));

General rule is simple: do not use PChar until at the very last moment. This way you don't need to think too much about memory management issues (well, mostly).

See also this great article.

只是偏爱你 2024-08-14 07:01:48

好吧,我想我可能已经明白了。

我使用的是匿名方法,因此编译器应该捕获我的局部变量。显然,它只捕获我在匿名方法中实际使用的变量。这意味着 CharPtr 被捕获,但 SendStr 未被捕获。因此,当 SendStr 超出范围时,它就会被破坏,并且 CharPtr 现在面临指向某些随机垃圾的危险。

通过以下修改,

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

一切似乎都工作正常。

Okay, I think I might have figured it out.

I'm using an anonymous method, so the compiler should capture my local variables. Apparently, it does only capture the variables that I actually use in the anonymous method. That means that CharPtr is captured but not SendStr. So, when SendStr falls out of scope it is destructed and CharPtr is now in danger of pointing to some random garbage.

With the following modification

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

everything seems to work fine.

温柔戏命师 2024-08-14 07:01:48

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

Why not pass the string by value, rather than pointer/reference?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文