утечка струны дельфи - PullRequest
       3

утечка струны дельфи

6 голосов
/ 24 марта 2011

Я работаю с Delphi XE и пишу приложение, которое использует RemObjects SDK для связи (в случае, если это может быть актуально). У меня включена отладка FastMM, и иногда (не всегда), когда я закрываю ее, выдается предупреждение об одной «неожиданной утечке памяти». «Произошла непредвиденная утечка памяти. Неожиданные утечки небольших блоков: 117-124 байта: UnicodeString x 1». Очень редко мне сообщают о x2.

Теперь, насколько я понимаю, строки считаются ссылками, и, поскольку нет другого объекта, который мог бы вызвать утечку, какая может быть ситуация, которая может вызвать это? В этом вопросе StackOverflow люди не могут найти способ утечки.

Если очевидного пути нет, я скачаю последний источник FastMM (он, похоже, не включен в источник XE).

[Править после разрешения] Решением этой проблемы было установить источник FastMM и включить FullDebugMode для получения трассировки стека.

Ответы [ 4 ]

7 голосов
/ 25 марта 2011

При использовании типизированных констант и в зависимости от порядка финализации FastMM имел возможность сообщать об утечке, когда ее на самом деле нет.

FastMM: произошла утечка памяти, в которой, как я полагаю, не должно быть.

Короче говоря, когда финализированный модуль get завершен, константа SString get освобождена.После завершения финализации модуля вызывается финализация FinalizedLast get.В финализации он вызывает метод LeakMemory метода FinalizedFirst.Переменная SString снова инициализируется и не освобождается, так как финализация FinalizedFirst уже запущена.

FinalizedLast Unit

unit FinalizedLast;    

interface

uses FinalizedFirst;

implementation

initialization LeakMemory;
finalization LeakMemory;
end.

Завершено Первый блок

unit FinalizedFirst;

interface

procedure LeakMemory;

implementation

uses FinalizedLast;

procedure LeakMemory;
const
  SString: string = '';
begin
  //***** SString will get initialized once or twice depending on the
  // finalization order of units. If it get's initialized twice,
  // a memory leak is reported.
  if SString = '' then
  SString := 'FooBar';
end;
end.

Project LeakMemory

program LeakMemory;
uses
FastMM4 in 'FastMM4.pas',
Forms,
FinalizedFirst in 'FinalizedFirst.pas',
FinalizedLast in 'FinalizedLast.pas';

{$R *.RES}
begin

Application.Initialize;
Application.Run;

end.
6 голосов
/ 24 марта 2011

Вы можете утечь строки, освободив записи в куче, используя FreeMem вместо Dispose, или если вы перезаписали запись, используя System.Move или FillChar.В первом случае код завершения не запускается, а во втором, если строковое поле заполнено нулем, он будет думать, что оно уже очищено.

Если вы хотите найти место для утечки, загрузите FastMMи включите FullDebugMode.Он будет включать в себя трассировку стека, где произошла утечка.

5 голосов
/ 25 марта 2011

Единственный способ, который приходит на ум, где вы можете пропустить строку, не умышленно ее разрывая (например, вручную увеличивая счетчик ссылок или выполняя некоторую грязную операцию указателя), - это использовать threadvar.

Как состояния файла справки,

Динамические переменные, которые обычно управляется компилятором (длинные строки, широкие строки, динамические массивы, варианты и интерфейсы) могут быть объявлено с помощью threadvar, но компилятор не освобождается автоматически выделенная куча память, созданная каждая нить исполнения. Если вы используете эти типы данных в переменных потока, это ваша ответственность распоряжаться их памяти изнутри нить, прежде чем нить прекратится.

Кроме того, на ум не приходит ничего, что еще не было заявлено.

[Редактировать спрашивающим] Это действительно было проблемой, и конкретный код был следующим:

threadvar
    g_szAuthentication : String;


procedure TMyBase.SetAuthentication(szUserName, szPassword: String);
begin
    g_szAuthentication := '?name=' + szUserName + '&pass=' + szPassword;
end;
4 голосов
/ 24 марта 2011

Я обычно вижу утечки строк, когда они содержатся внутри других объектов, которые не были уничтожены должным образом. Например, объект, который не был освобожден. Однако вы ожидаете увидеть и этот объект, о котором сообщается.

Чтобы решить эту проблему, загрузите и используйте полную версию FastMM и настройте ее так, чтобы она сообщала о трассировке стека при обнаружении утечек. Когда вы сделаете это, вы получите полную трассировку стека кода, который выделил утечку объекта, и в этот момент обычно становится ясно, в чем проблема.

...