jpfollenius
jpfollenius

Reputation: 16612

Premature string destruction and how to avoid it?

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.

Upvotes: 1

Views: 217

Answers (4)

Alex
Alex

Reputation: 5668

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.

Upvotes: 4

Wim Coenen
Wim Coenen

Reputation: 66733

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);

Upvotes: 7

jpfollenius
jpfollenius

Reputation: 16612

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.

Upvotes: 2

Preet Sangha
Preet Sangha

Reputation: 65506

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

Upvotes: 0

Related Questions