哪个更好: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, FreeFreeAndNil之间的区别在于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两个论点,这是由你来决定是否喜欢与否。