假设一个应用程序在启动时只创建了一些表单和一个数据模块。在DM1.OnCreate
事件中,会创建一个TStringList
,以便在运行时使用。我们知道,当应用程序被终止时,所有的东西都会被破坏,内存会自动释放。释放某些内容可能需要一些时间,因此建议不要总是担心关闭时内存泄漏。例如,请参阅Barry Kelly的回答或Raymond Chen的帖子。
除此之外,如果我不将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;
出于同样的原因,我强烈主张(轻描淡写)不要在项目中留下任何编译器提示或警告,请自己清理干净,不要留下报告的内存泄漏
永远
现在,如果您有充分的理由不这样做,这并不一定意味着您必须释放DataModule的Destructor中的所有内容,但在这种情况下,您需要注册内存泄漏,这样它就不会被报告。(并发表了一条非常明显的评论来证明和解释原因)
但考虑到你可能会离开这个项目,一年后,其他人正在维护它,并有创建多个DataModule的新业务需求。。。很可能,如果他们对你的代码内部了解不够深入,他们会相信你的代码是干净的,问题很可能随之而来。
因此,我强烈建议不要释放,除非是在一个非常特殊、预期和记录在案的案件中。。。
PS:看到这一点,我不得不多次清理掉掉掉得到处都是的内存,甚至我还做了一些关于防止内存泄漏的CodeRage会议。。。
更新:以下是下载CodeRage会话的链接。。。
我的回答可以被认为是哲学性的,但主要原因是任何行动(或不行动)都会产生后果。我考虑了你的例子,可能还有其他的例子,我看到了释放这个对象的一个很好的理由。每次我认为我可以忽略释放对象,都会增加在其他情况下,可能更严重的情况下不这样做的概率。另一个例子是,在分配或释放某个东西的任何地方,都有"尝试最终结束"的习惯。我不在乎在出现异常时释放,但这个习惯可以帮助我避免泄露
对于有意的内存泄漏,请使用RegisterExpectedMemoryLeak
。该例程有几个重载版本,其中一个版本可以用对象类:
begin
RegisterExpectedMemoryLeak(TStringList);
FStringList := TStringList.Create;
...
或者更好的是,注册指针本身:
begin
FStringList := TStringList.Create;
RegisterExpectedMemoryLeak(FStringList);
...
在这种情况下,意外的内存泄漏将正常显示,并且不能与此特定的字符串列表混淆。
让我问你一个问题来回答。
您是否可以肯定地说,数据模块的生命周期将始终与应用程序的生命周期相关联,或者您将永远不需要创建它的其他实例?
如果您的回答是肯定的,那么可以忽略标准的内存管理实践。
若你们的回答是否定的,那个么你们应该确保物体在它们自己之后被清理干净。
当您释放一个对象时,事情就完成了,可能更多的是只释放内存。
脑海中浮现的是一个数据库对象,它执行事务并在ondestroy中结束所有启动的事务。
如果你不打免费电话,ondestroy不会被解雇,你可能会被锁上桌子。