Преждевременное разрушение струны и как этого избежать? - PullRequest
1 голос
/ 06 октября 2009

Я использую Delphi 2009 и получаю некоторые странные ошибки, используя следующий сегмент кода:

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

Я предполагаю, что строка разрушается при выходе из области видимости и при некоторых временных условиях DoSomething даст самые странные результаты. Итак, первый вопрос: я прав?

Второй вопрос: как я могу обойти разрушаемую нить? Как правильно это сделать?

Заранее спасибо.

Ответы [ 4 ]

7 голосов
/ 06 октября 2009

Итак, первый вопрос: я прав?

Скорее всего, да. AnsiString Delphi является подсчетом ссылок. Когда Str выходит из области видимости, счетчик ссылок уменьшается. Если счетчик ссылок достигает нуля, то память, которую он занимал, может быть использована повторно.

Второй вопрос: как я могу обойти струну подорванный? Какой правильный способ к этому?

Не используя указатели, например:

var
  Str     : AnsiString;
...
ExecuteInBackgroundThread (
  procedure
  begin
  DoSomething (Str);
  end);
4 голосов
/ 06 октября 2009

Просто используйте:

DoSomething(PAnsiChar(Str));

Общее правило простое: не используйте PChar до самого последнего момента . Таким образом, вам не нужно слишком много думать о проблемах управления памятью (ну, в основном).

См. Также эту замечательную статью .

2 голосов
/ 06 октября 2009

Ладно, думаю, я бы понял.

Я использую анонимный метод, поэтому компилятор должен перехватывать мои локальные переменные. По-видимому, он фиксирует только те переменные, которые я фактически использую в анонимном методе. Это означает, что CharPtr перехвачен, но не SendStr. Таким образом, когда SendStr выходит из области видимости, он разрушается, и CharPtr теперь может указывать на случайный мусор.

со следующей модификацией

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

все вроде нормально работает.

0 голосов
/ 06 октября 2009

Почему бы не передать строку по значению, а не по указателю / ссылке?

...