8

假设一个具有一些表单的应用程序在开始时只创建了一个数据模块。在这种情况DM1.OnCreate下,将TStringList创建 a 以在运行时使用。我们知道,当应用程序被终止时,所有东西都会被销毁,内存会自动释放。释放某些东西可能需要一些时间,因此并不总是建议担心关机时的内存泄漏。例如,参见Barry Kelly的这个答案或 Raymond Chen的这篇文章

除此之外,如果我不添加TStringList.FreeDM1.OnDestroy. 在搜索我真正应该担心的任何其他内存泄漏时,这成为一个问题。

所以基本上我在问我是否/为什么/何时应该释放将由应用程序或操作系统(在这种特定情况下为 Windows)释放的对象实例。在寻找内存泄漏时是否还有其他有效案例?

注意:在这种特定情况下,不会多次创建或重新创建数据模块。除了一个之外,根本不会有任何内存泄漏。数据模块报废来源:

unit UDM1;

interface

uses SysUtils, Classes, ...;

type
  TDM1 = class(TDataModule)
    procedure DataModuleCreate(Sender: TObject);
    procedure DataModuleDestroy(Sender: TObject);
    procedure DoStuffWithStringList1(Sender: TObject);
  private
    internalStL: TStringList;
  end;

var
  DM1: TDM1;

implementation

procedure TDMInterfacePAFECF.DataModuleCreate(Sender: TObject);
begin
  internalStL := TStringList.Create();
end;

procedure TDMInterfacePAFECF.DataModuleDestroy(Sender: TObject);
begin
  internalStL.Free; //<-- IS THIS NECESSARY OR ADVISED?
end;

procedure DoStuffWithStringList(Sender: TObject);
begin
  //Place some code using internalStL here...

end;
4

5 回答 5

7

出于同样的原因,我强烈主张(轻描淡写)不要在项目中留下任何编译器提示或警告,自己清理并且不要留下报告的内存泄漏!
曾经!

现在,这并不一定意味着如果您有充分的理由不这样做,您必须释放 DataModule 的析构函数中的所有内容,但在这种情况下,您需要注册您的内存泄漏,这样它就不会被报告。(并放一个非常明显的评论来证明和解释原因)

但考虑到您可能会离开这个项目,并且一年后,其他人正在维护它并且有一个新的业务需求来创建多个 DataModules... 如果他们对您的代码内部了解得不够透彻,他们会相信您的代码是干净的,并且可能会出现问题。

所以我强烈建议不要释放,除非在一个非常特殊和预期和记录的情况下......

PS:看到这一点,不得不多次清理掉到处都是的内存,以至于我什至做了一些关于对抗内存泄漏的 CodeRage 会议......

Updayte:这是下载CodeRage 会话的链接......

于 2012-03-27T19:29:23.310 回答
7

我的回答可以被认为是哲学的,但主要原因是任何行动(或不采取行动)都会产生后果。我考虑了您的示例以及可能的其他示例,并且我看到了释放该对象的一个​​很好的理由。每次我认为我可以忽略释放对象时,都会增加在其他可能更严重的情况下不这样做的可能性。另一个例子是在分配或释放某些东西的任何地方都做“尝试最终结束”的习惯。我不在乎在异常情况下释放,但是这个习惯可以帮助我避免泄漏

于 2012-03-27T19:05:44.147 回答
5

用于RegisterExpectedMemoryLeak故意的内存泄漏。该例程有几个重载版本,其中一个可以使用对象类进行输入:

begin
  RegisterExpectedMemoryLeak(TStringList);
  FStringList := TStringList.Create;
  ...

或者更好的是,注册指针本身:

begin
  FStringList := TStringList.Create;
  RegisterExpectedMemoryLeak(FStringList);
  ...

在这种情况下,意外的内存泄漏将正常显示,并且不能与这个特定的字符串列表混淆。

于 2012-03-27T19:22:25.017 回答
4

让我通过问你一个问题来回答。

您是否可以肯定地说数据模块的生命周期将始终与应用程序的生命周期相关联,或者您永远不需要创建它的其他实例?

如果您回答“是”,则可以随意忽略标准内存管理实践。

如果你回答否,那么你应该确保对象自己清理干净。

于 2012-03-27T18:59:54.967 回答
2

当你释放一个对象时,事情就完成了,可能不仅仅是释放内存。

想到一个数据库对象,它执行事务并在 ondestroy 中结束所有已启动的事务。

如果您不调用 free,ondestroy 将不会被解雇,并且您最终可能会锁定表。

于 2012-03-28T08:44:17.047 回答