Trying to fix memory leaks in my application using FastMM in full debug mode, some leaks are reported regarding instances of (descendants of) TForm. After checking and stepping in the code, I can say for sure that those forms are released and not freed. It looks as if FastMM is checking for leaks before the actual freeing scheduled by Release happens.
MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Release; // FastMM reports MyForm as a leak
I tried freeing them instead, and those memory leaks are no longer being reported, but sometimes, an access violation occurs when freeing:
MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Free; // // FastMM does not report MyForm as a leak, but sometimes an access violation is triggered
I tried releasing them, and call Application.ProcessMessages immediately after, as I understood could be done reading Zoë Peterson's answer in https://stackoverflow.com/a/917187/1465896. I must have understood wrong, because it crashes always immediately in Application.ProcessMessages:
MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Release;
Application.ProcessMessages; // always triggers an access violation
I don't want to register those forms as expected memory leaks, because they contain more objects that clutter the memory leak log file, making it harder to find more important leaks.
So my question is, how to properly free a Delphi form so that FastMM won't report it as a leak?
As requested, here is an SSCnCE (Short, Self Contained, Correct (not Compilable as is because I don't know how to post the project), Example):
File FormRelease.dpr:
program FormRelease;
uses
FastMM4 in 'FastMM4.pas',
Vcl.Forms,
MainForm_fm in 'MainForm_fm.pas' {MainForm},
MyForm_fm in 'MyForm_fm.pas' {MyForm};
{$R *.res}
begin
Application.Initialize;
Application.MainFormOnTaskbar := True;
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end.
File MainForm_fm.pas:
unit MainForm_fm;
interface
uses
Vcl.Forms,
MyForm_fm;
type
TMainForm = class(TForm)
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FMyForm: TMyForm;
end;
var
MainForm: TMainForm;
implementation
{$R *.dfm}
procedure TMainForm.FormCreate(Sender: TObject);
begin
FMyForm := TMyForm.Create(nil);
end;
procedure TMainForm.FormDestroy(Sender: TObject);
begin
FMyForm.Release;
end;
end.
File MyForm_fm.pas:
unit MyForm_fm;
interface
uses
Vcl.Forms;
type
TMyForm = class(TForm)
end;
implementation
{$R *.dfm}
end.
Excerpt from file FormRelease_MemoryManager_EventLog.txt, after starting the program and stopping it with alt-F4:
This application has leaked memory. The small block leaks are (excluding expected leaks registered by pointer):
13 - 20 bytes: TList x 1, Unknown x 1
21 - 36 bytes: TPen x 1, TMargins x 1, TPadding x 1, TIconImage x 1, TBrush x 2, TTouchManager x 1, TSizeConstraints x 1, UnicodeString x 1, Unknown x 3
37 - 52 bytes: TGlassFrame x 1, TFont x 2
53 - 68 bytes: TIcon x 1
69 - 84 bytes: TControlScrollBar x 2
101 - 116 bytes: TControlCanvas x 1
149 - 164 bytes: Unknown x 1
917 - 1012 bytes: TMyForm x 1
Why is there TMyForm x 1
left if the CM_RELEASE
posted with FMyForm.Release
has been handled?
finalization
section (the application I have to fix has a somewhat peculiar architecture). – PapayaRelease
does not free the form. – Papaya