除了寻找内存泄漏之外,还有其他情况我应该在销毁应用程序时释放所有对象吗?

时间:2012-03-27 18:40:21

标签: delphi memory-leaks free fastmm

假设在开始时创建了具有某些表单且只有一个数据模块的应用程序。 在DM1.OnCreate事件中,创建了TStringList以在运行时使用。 我们知道,当应用程序被终止时,所有内容都将被销毁,内存将自动释放。释放某些东西可能需要一些时间,因此并不总是建议担心关机时的内存泄漏。例如,请参阅Barry Kelly的this answer或Raymond Chen的this post

除此之外,如果我没有将TStringList.Free添加到DM1.OnDestroy,FastMM会报告内存泄漏。在搜索我应该真正担心的任何其他内存泄漏时,这会成为一个问题。

所以基本上我问是否/为什么/何时应该释放将被应用程序或操作系统释放的对象实例(在这种特定情况下为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;

5 个答案:

答案 0 :(得分:7)

我的回答可以被认为是哲学的,但主要原因是任何行动(或没有行动)都会产生后果。我想到了你的例子,可能还有其他例子,我看到一个很好的理由来释放这个对象。每次我认为我可以忽略释放对象增加了在其他情况下不这样做的可能性,也许更严重的情况。另一个例子是习惯做到&#34;尝试最后结束&#34;在任何地方分配或释放某些东西。如果出现异常,我不会在乎自由,但这种习惯可以帮助我避免泄漏

答案 1 :(得分:7)

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

现在,这并不一定意味着你必须释放DataModule的析构函数中的所有东西,如果你有一个强有力的例子没有这样做,但在这种情况下,你需要注册你的内存泄漏所以不会被报道。 (并提出一个非常明显的评论来证明并解释原因)

但是考虑一下你可能离开这个项目一年后,其他人正在维护它并且有一个新的业务需求来创建多个DataModule ...如果他们不知道代码的内部,那么很可能好吧,他们会相信你的代码是干净的,并且可能会出现问题。

所以我强烈建议不要放行,除非在非常特殊和预期的案例中......

PS:看到了这一点,不得不擦掉内存遍布整个地方的次数,以至于我甚至做了一些关于内存泄漏的CodeRage会议......

Updayte:以下是下载that CodeRage session的链接...

答案 2 :(得分:5)

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

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

或更好,注册指针本身:

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

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

答案 3 :(得分:4)

让我回答问你一个问题。

您能否确定数据模块的生命周期始终与应用程序的生命周期相关联,或者从不需要创建其他实例它?

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

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

答案 4 :(得分:2)

当你释放一个对象时,东西会被完成,可能只会释放内存。

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

如果您没有免费拨打电话,ondestroy将不会被解雇,您最终可能会使用锁定的桌子。