哪个更好:Free还是FreeAndNil?
Free和FreeAndNil有什么区别?
FreeAndNil = Free + Nil?
什么时候应该使用Free,何时应该使用FreeAndNil?
当有人能帮我的时候,我没有得到这些东西。
提前致谢。
看到
- delphibasics-FreeAndNil
- docwiki.embarcadero-FreeAndNil
- 页面,freeandnil
- eurekalog-freeandnil
- blogs.embarcadero
- …
并看看执行情况:
procedure FreeAndNil(var Obj); var Temp: TObject; begin Temp := TObject(Obj); Pointer(Obj) := nil; Temp.Free; end;
例子
考虑下面的代码:
procedure TForm1.FormCreate(Sender: TObject); var bm: TBitmap; begin bm := TBitmap.Create; bm.LoadFromFile('C:\Users\Andreas Rejbrand\Documents\RAD Studio\6.0\Demos\DelphiWin32\VCLWin32\Football\up.bmp'); bm.Free; if Assigned(bm) then bm.SaveToFile('C:\Users\Andreas Rejbrand\Desktop\test.bmp') else ShowMessage('Cannot save! The bitmap does no longer exist!'); end;
这将在我的桌面上创build一个错误或无效(空)位图,因为我尝试使用已释放的对象。 是的,即使bm
已经被释放,它仍然是“分配”的,即bm
仍然指向一个内存地址,即使这里没有任何东西(可用)。 为了克服这个问题,可以设置bm := nil
作为安全措施,然后根据需要assigned(bm)
将返回false。 或多或less, FreeAndNil(bm)
是bm.Free; bm := nil
的缩写bm.Free; bm := nil
bm.Free; bm := nil
。 第一条语句释放所有内存(以及对象使用的操作系统资源,CPU时间等),而bm := nil
将“指针” bm
设置nil
,以便bm
不再指向对象过去的地方,但不再是。 这样,你(和像assigned
例程)不会被愚弄,相信仍然有一个位图对象。
讨论
有人说你应该总是使用FreeAndNil(foo)
而不是foo.Free
。 那么,为什么不呢? 附加指令foo := nil
可能不会花费太多的纳秒来执行,而assigned(foo) = false
是释放对象的一个非常好的属性。 但是如果你知道自己在做什么,并且知道你将永远不会再使用foo
对象,那么你可以坚持只是foo.free
。 实际上,有些人会认为,在很多情况下(但不是全部),试图使用释放对象的variables本身就是一个错误。 (当然,有些情况下你有意这样做 – 你有一个对象foo
有时被分配,有时不是)。
FreeAndNil基本上将引用设置为零 ,然后释放对象。 这标记为未分配。 所以你需要使用FreeAndNil的唯一原因是如果你的代码要重用这个引用。 如果你在析构函数或finally块中,释放你永远不会再碰的对象,只需使用Free。
有关我发现它很有用的示例,请参阅Delphi内存pipe理简单 。 Mghie在底部的评论也值得一读。
我会以不同的方式回答。
也许,在释放对象后用nil
填充对象引用并不总是一个好主意。
这样,你没有区别一个从来没有使用的参考(因此是nil
),和一个已经使用的参考,但不应该在将来使用。
因此,填充一个幻数(类似于FastMM内存pipe理器在释放这些块时可以对内存块内容进行的操作)。
–jeroen
@Bharat, Free
和FreeAndNil
之间的区别在于FreeAndNil
将对象引用设置为nil,此外FreeAndNil
还使用了空闲内存。
你可以查看这些链接,讨论使用Free或FreeAndNil的讨论
- 一个针对FreeAndNil的案例
- 不要滥用FreeAndNil了
- JWSCL和FreeAndNil
- JWSCL和FreeAndNil的第二次尝试
即使看起来和Free不太一样,它会在你寻找代码的时候帮助你很多。
只要想一想,如果你不使用FreeAndNil,然后在代码的某个地方访问一个释放的对象,会发生什么。 如果你太幸运了,你的程序在运行时会崩溃(是的,这是一个“好”的崩溃)。 如果你有点不幸,它会在客户的电脑上崩溃。 然后真正的痛苦开始!
正如其他人已经指出,FreeAndNil本身并不坏。 FreeAndNil函数没有被破坏/废弃或者类似的东西,它不会破坏你的代码。 有人会认为,依靠FreeAndNil可能会导致或指出一个devise缺陷。
我在一个局部variables上使用了FreeAndNil。 在局部variables上使用它似乎是POINTLESS,因为一旦你退出这个过程variables就会消失。 但是,这是一个很好的做法,只会花费额外的几个字节。 想想以后你可以在程序结尾添加更多的代码,在释放对象之后,代码将会(显然是偶然的)尝试访问释放的对象。 如果对象是NIL,BABUM,即时AV( 例子 )。
注意:有些人可能会说他们从来没有访问过一个自由对象(基本上是指他们从不犯错误),所以在这种情况下他们不需要FreeAndNil。 那么,我不是一个机器人。 我犯了错误。
一些保守的人可能会说这个简单的调用会浪费内存和CPU资源。 我永远不会说保存内存/ CPU是坏的。 我喜欢提供小型/快速/单片应用程序! 但我不认为使用FreeAndNil将会浪费更多的字节和CPU周期(字面上很less)。 它不会在日常生活中产生真正的变化,特别是当您认为像TButton字形或程序图标这样的单个graphics资源可能需要50-300KB,并且您的程序可能有几十个这样的。
优点
梅森惠勒已经指出了一个文章,显示使用FreeAndNil,我们有一天使用的“懒惰创造”的方法: http ://tech.turbu-rpg.com/106/delphi-memory-management-made-simple
缺点
Allen Bauer在这里展示了一个关于如何在一个特定的情况下使用FreeAndNil(一个可视化组件的析构函数)的例子,并且确实很糟糕: http : //blogs.embarcadero.com/abauer/2010/02/16/38916
艾伦指出FreeAndNil应该被更好的方法取代。 例如FastMM。 然而,下面是一段简单的代码,其中FastMM失败,而FreeAndNil则保存一天: http ://codeverge.com/embarcadero.delphi.rtl/freeandnil-to-use-or-not-to-use/1067733
既然有赞成和反对FreeAndNil两个论点,这是由你来决定是否喜欢与否。