Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

delphi string leak

I'm working with Delphi XE, and writing an application that is using RemObjects SDK to communicate (in case that may be relevant). I have FastMM debug on, and sometimes (not always) when I close it gives a warning about a single "Unexpected Memory Leak". "An unexpected memory leak has occurred. The unexpected small block leaks are: 117-124 bytes: UnicodeString x 1". Very occasionally, I get x2 reported.

Now, my understanding is that Strings are reference counted, and since there is no other object involved to cause the leak, what might be the situation that could cause this to happen? In this StackOverflow question people cannot find a way to make a leak.

If there is no obvious way, then I will download the latest FastMM source (it appears not to be included with the XE source).

[Edit once resolved] The solution to finding this was to install FastMM source, and enable the FullDebugMode to get the stack trace.

like image 527
mj2008 Avatar asked Mar 24 '11 17:03

mj2008


2 Answers

When using typed constants and depending on finalization order, it used to be possible for FastMM to report a leak when there really isn't.

FastMM: Leaked memory reported where I believe it shouldn't.

In short, when the FinalizedFirst unit get's finalized, the SString constant get's freed. After finalization of the unit is done, the finalization of FinalizedLast get's called. In it is finalization, it call's the method LeakMemory of the FinalizedFirst method. The SString variable gets initialized again and doesn't get freed as the finalization of FinalizedFirst has already run.

FinalizedLast Unit

unit FinalizedLast;    

interface

uses FinalizedFirst;

implementation

initialization LeakMemory;
finalization LeakMemory;
end.

FinalizedFirst Unit

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.
like image 80
Lieven Keersmaekers Avatar answered Oct 12 '22 22:10

Lieven Keersmaekers


You can leak strings by freeing records on the heap using FreeMem instead of Dispose or if you overwrite a record using System.Move or FillChar. In the first case the finalization code isn't run and in the second if the string field was filled with a nil it will think it's already cleared it.

If you want to find the location for the leak download FastMM and turn on FullDebugMode. It will include a stack trace of where the leak occurred.

like image 31
Zoë Peterson Avatar answered Oct 12 '22 20:10

Zoë Peterson