Delphi 我需要释放动态创建的表单吗?

Delphi 我需要释放动态创建的表单吗?,delphi,memory-management,Delphi,Memory Management,如果我使用TForm.CreateNew(应用程序)动态创建一个TForm来创建一个自由浮动窗口,我是否必须跟踪这些对象并在应用程序关闭时释放它们 或者delphi会在应用程序关闭时自动释放所有表单吗 另外,如果我有一个自由浮动的动态创建表单,并且用户点击关闭按钮,会发生什么?我需要在某个地方调用一些代码来释放这些吗? 如果是,怎么做?我假设我不能将它放在表单的任何事件中。传递给CreateNew的参数是组件的所有者。当一个组件的所有者被销毁时,它将销毁它所拥有的所有组件。因此,应用程序对象是表

如果我使用TForm.CreateNew(应用程序)动态创建一个TForm来创建一个自由浮动窗口,我是否必须跟踪这些对象并在应用程序关闭时释放它们

或者delphi会在应用程序关闭时自动释放所有表单吗

另外,如果我有一个自由浮动的动态创建表单,并且用户点击关闭按钮,会发生什么?我需要在某个地方调用一些代码来释放这些吗?

如果是,怎么做?我假设我不能将它放在表单的任何事件中。

传递给
CreateNew
的参数是组件的所有者。当一个组件的所有者被销毁时,它将销毁它所拥有的所有组件。因此,应用程序对象是表单的所有者。当应用程序关闭时,应用程序对象将被销毁。因此,它会销毁其所有的组件。包括动态创建的表单

我需要释放动态创建的表单吗

不,除非您使用
TForm.CreateNew(nil)
创建表单,该表单不向构造函数传递所有者

CreateNew
的参数是所有者,如果所有者(应用程序/表单/WhatEverYouLike)被删除,所有拥有的对象都将被释放。试试看

procedure TMainfom.Button1Click(Sender: TObject);
var
 a:TForm;
begin
 With Tform.CreateNew(Application) do
   begin
   OnClose := MyAllFormClose;
   OnDestroy := AllMyFormDestroy;
   Show;
   end;
end;

procedure TMainfom.AllMyFormDestroy(Sender: TObject);
begin
   Showmessage(':( I''m going to be destroyed')
end;

procedure TMainfom.MyAllFormClose(Sender: TObject; var Action: TCloseAction);
begin
  // unremark if you want to get the form freed OnClose already 
  // Action := caFree;    
end;

只是想谈谈其他答案中未涉及的一个重要问题

是的,当您与所有者一起创建表单(或任何其他组件)时,当所有者被销毁时,表单将被销毁。
但是,非常注意:这并不意味着你不会有漏洞。澄清:

  • 如果每次创建表单时都将
    应用程序
    设置为所有者,则当应用程序关闭时,
    应用程序
    对象将销毁表单
  • 但是(除非您编写了额外的代码),只有当应用程序关闭时,这些表单才会被销毁
  • 换句话说,如果每次用户选择特定菜单项时,您都创建了应用程序所拥有的特定表单,那么随着时间的推移,将消耗更多内存。根据每次创建表单时使用的内存量,应用程序可能会耗尽内存
因此,如果您不继续重新创建对象,那么模型是完全可以接受的。但是,这意味着您确实希望跟踪这些对象。但这并不是为了让您自己释放它们,而是为了让您可以重新显示它们,而不是重新创建它们


此外,还包括您问题中的其他几点:

如果我有一个自由浮动的动态创建表单窗口,用户点击关闭按钮,会发生什么?我需要在某处调用一些代码来释放这些吗

如果下次用户显示表单时重用现有实例,则不需要释放它们。如果要创建一个新实例,那么应该在窗体关闭时释放它。否则,只有当应用程序关闭时,所有旧实例才会被销毁

怎么做?我想我不能把它放在表单的任何事件中

碰巧Delphi提供了一个理想的事件:
OnClose
。如果挂接该事件,则可以设置
var Action:TCloseAction
以指示表单关闭时应该发生什么。默认情况下:

  • MDI表单将最小化(
    caMinimize
  • SDI表单将被隐藏(
    caHide
您可以更改此选项以销毁表单(
caFree


注意:如果您决定销毁表单,请小心不要在表单销毁后尝试重新使用它。任何指向窗体的变量都将指向内存中的同一位置,但窗体不再存在。

我不知道为什么人们似乎认为窗体是某种神奇的实体,有自己独特的行为和规则

表单是从TForm和TCustomForm派生的常规对象,它们最终是从TObject派生的,就像Delphi中的所有其他类一样

如果动态创建从TObject派生的任何内容,则当应用程序终止时,它将被销毁。但是,如果您未能自行销毁它并将其留给系统,则通常被视为“内存泄漏”。对于只运行一次并快速终止的程序来说,这不是什么大不了的事。但是,对于那些用户会连续几小时或几天打开的东西,内存泄漏可能会成为一个相当麻烦的问题

如前所述,TForms有一个OnClose事件,该事件具有参数操作。您可以将Action设置为caFree,当返回到显示表单的Show或showmodel调用时,表单将被销毁。但是如果使用它,则需要自己创建表单对象,而不是使用默认的自动创建机制


其他类型的对象没有这个功能,比如TStringList。您只需要练习“安全对象管理”,并确保创建的对象也能及时销毁,包括表单。这可能会引发一场关于垃圾收集、接口和大量相关内容的讨论。可以说,您需要了解这些选项并适当地管理对象生命周期,而不是让它们在应用程序终止时被销毁。

更好的方法是为所有动态创建的表单创建一个基本表单,并覆盖
TForm.DoClose
方法并设置
Action:=caFree;继承的
将其作为默认选项。现在,可以像往常一样安全地使用
OnClose
事件,而不会产生副作用感谢刷新。。。在德尔福流行的那一天,我非常擅长德尔福。但是再次使用它是新的(我需要做一个小工具),所以我忘记了一些基本的东西,比如说!。也许值得扩展您的最后一段,提到接口等与TObject子体属于不同的类别,因为编译器生成代码来主动“管理”它们的子体