繁体   English   中英

如何正确释放Delphi表单

[英]How to properly free a Delphi form

尝试在完全调试模式下使用FastMM修复我的应用程序中的内存泄漏时,报告了有关TForm(后代)实例的一些泄漏。 在检查并进入代码之后,我可以肯定地说那些表单已经释放而不是释放 看来FastMM在Release计划的实际释放发生之前正在检查泄漏。

MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Release; // FastMM reports MyForm as a leak

我尝试释放它们,并且不再报告那些内存泄漏,但是有时释放时会发生访问冲突:

MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Free; // // FastMM does not report MyForm as a leak, but sometimes an access violation is triggered

我试着释放它们,然后立即调用Application.ProcessMessages,据我了解可以阅读https://stackoverflow.com/a/917187/1465896中的 ZoëPeterson的回答。 我肯定理解错了,因为它总是在Application.ProcessMessages中立即崩溃:

MyForm: TForm;
MyForm := TForm.Create(nil);
...
MyForm.Release; 
Application.ProcessMessages; // always triggers an access violation 

我不想将这些表单注册为预期的内存泄漏,因为它们包含更多的对象,这些对象会使内存泄漏日志文件变得混乱,从而使查找更重要的泄漏变得更加困难。

所以我的问题是,如何正确释放Delphi表单,以使FastMM不会将其报告为泄漏?

根据要求,这是一个SSCnCE(简短,自包含,正确(不能编译,因为我不知道如何发布项目),示例):

文件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.

文件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.

文件MyForm_fm.pas:

unit MyForm_fm;

interface

uses
  Vcl.Forms;

type
  TMyForm = class(TForm)
  end;

implementation

{$R *.dfm}

end.

在启动程序并使用alt-F4停止之后,摘录自文件FormRelease_MemoryManager_EventLog.txt。

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

如果已处理与FMyForm.Release CM_RELEASE发布的CM_RELEASE为什么还TMyForm x 1

听起来好像是两件事。

首先,您要显式创建表单,因此应显式释放它。 除特殊情况(例如表单从其自身的事件处理程序之一中释放自身)外,您无需调用Release。

MyForm: TForm;
...
MyForm := TForm.Create(nil);
try
  // Only reference MyForm in this block
finally
  MyForm.Free;
end;

其次,致电Free不会引起问题。 我认为它正在揭示它。 如果我不得不猜测,则会发生访问冲突,因为在此块之外引用了MyForm或其组件之一。 使用调试器查找此引用并进行修复。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM