I have encountered a memory leak problem with a Delphi 7 application(CLX), with a piece of code like the following :
unit Unit2;
interface
uses ECRClass, ECR_Text, SysUtils, Types, Classes, Variants, Math;
type tLeakClass = class
private
fsType : integer;
public
fsPrinter : TECR_Class;
published
constructor Create (AOwner : TComponent);
destructor Destroy();
end;
implementation
constructor tLeakClass.Create (AOwner : TComponent);
begin
fsPrinter := TECR_Text.Create(AOwner);
end;
destructor tLeakClass.Destroy();
begin
fsPrinter.Free
end;
end.
the object fsPrinter
result leaked even if it is freed at the moment that the main form(TForm) close :
unit Unit1;
interface
uses
SysUtils, Types, Classes, Variants, QTypes, QGraphics, QControls, QForms,
QDialogs, QStdCtrls, Unit2;
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
tleak : tLeakClass;
end;
var
Form1: TForm1;
implementation
{$R *.xfm}
procedure TForm1.Button1Click(Sender: TObject);
begin
tLeak := tLeakClass.Create(Self);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
tleak.Free
end;
end.
Here's the report of the leak by FastMM4 :
A memory block has been leaked. The size is: 740
This block was allocated by thread 0xBA8, and the stack trace (return addresses) at the time was:
402F1C [system.pas][System][@GetMem][2439]
403C77 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
502F15 [ECR_Text.pas][ECR_Text][TECR_Text.Create][101]
403C80 [system.pas][System][TObject.NewInstance][8360]
404012 [system.pas][System][@ClassCreate][9019]
5030C6 [Unit2.pas][Unit2][tLeakClass.Create][24]
43856C [QStdCtrls.pas][QStdCtrls][2863]
503300 [Unit1.pas][Unit1][TForm1.Button1Click][30]
447076 [QControls.pas][QControls][TControl.Click][1977]
43858C [QStdCtrls.pas][QStdCtrls][TButton.Click][2871]
The block is currently used for an object of class: TECR_Text
Here you can download a full SSCCE example of a project that represent the problem(to run the example one click on the button and close the form).
Why the fsPrinter
object leaks ? How can I avoid the leak ?
You destructor is declared incorrectly. You wrote:
But you must override the virtual destructor declared in
TObject
. If you don't then your destructor will not be called byFree
which calls the virtual destructor declared inTObject
.Fix it like this:
Although it doesn't matter in this case, you should get in to the habit of calling the inherited constructors and destructors in your constructors and destructors. That way, when you derive from a class that does more than
TObject
does in its constructors and destructors, you will make sure the superclass code runs.The FastMM report is a bit odd though. It reports that the
TECR_Text
object is leaked. But since you created that as owned by the form, the form should take it down. The object that is clearly leaked in the code in the question is the instance oftLeakClass
So I suspect that there are other problems in the classes that we cannot see. Quite possibly you made the same error and omitted the
override
on the destructors of the classes that we cannot see.