Free和FreeAndNil之间的基本区别是什么?
FreeAndNil = Free + Nil?
我应该何时使用Free,何时使用FreeAndNil?
当有人帮助我时,我没有得到这些。
提前致谢。
答案 0 :(得分:42)
见
看看实施情况:
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;
这将在我的桌面上创建错误或无效(空)位图,因为我尝试使用已释放的对象。是的,即使bm
已被释放,它仍然被“分配”,即bm
仍然指向内存地址,即使那里没有任何东西(可用)。为了解决这个问题,可以设置bm := nil
作为安全措施,然后assigned(bm)
将返回false,就像人们想要的那样。或多或少,FreeAndNil(bm)
是bm.Free; bm := nil
的简写。第一个语句释放所有内存(以及操作系统资源,对象使用的CPU时间等),bm := nil
将“指针”bm
设置为nil
,以便{{1} }不再指向曾经是对象的地方,但不再指向。这样你(以及像bm
这样的例程)就不会因为相信仍然存在位图对象而被愚弄。
有人说你应该总是使用assigned
而不是FreeAndNil(foo)
。好吧,为什么不呢?附加指令foo.Free
可能不会花费太多纳秒来执行,实际上foo := nil
是一个释放对象的非常好的属性。但话又说回来,如果你知道自己在做什么,并且知道在释放它之后再也不会再使用assigned(foo) = false
对象,那么你可以坚持foo
。实际上,有些人会争辩说,在许多情况下(但不是全部),尝试使用自由对象的变量本身就是一个错误。 (当然,有些情况下你有意这样做 - 你有一个有时被分配的对象foo.free
,有时却没有。)
答案 1 :(得分:18)
基本上,FreeAndNil将引用设置为 nil ,然后释放对象。这标志着它是未分配的。因此,您需要使用FreeAndNil的唯一原因是您的代码将重用该引用。如果您在析构函数或最终块中,释放您永远不会再触摸的对象,只需使用Free。
有关我发现它有用的示例,请参阅Delphi Memory Management Made Simple。 Mghie在底部的评论也值得一读。
答案 2 :(得分:8)
我会以不同的方式回答。
也许,在释放对象后用nil
填充对象引用并不总是一个好主意。
这样,您没有区分从未使用过的引用(因此是nil
),以及已经使用过但不应在将来使用的引用。
所以,用一个幻数填充它(类似于FastMM内存管理器在释放这些块时可以对内存块的内容做什么)。
- 的Jeroen
答案 3 :(得分:6)
@Bharat,Free
和FreeAndNil
之间的区别在于,除了对象FreeAndNil
使用的空闲内存外,还将对象引用设置为nil。
您可以查看这些链接,了解有关使用Free或FreeAndNil的讨论
答案 4 :(得分:2)
即使看起来与Free没有太大的不同,它也可以帮助你找到错误的代码。
想想如果你不使用FreeAndNil然后在代码中的某个地方访问一个释放的对象会发生什么。如果你很幸运,你的程序会在它运行回家时崩溃(是的,崩溃是'好'的崩溃)。如果你有点不走运,它会在客户的电脑中崩溃。然后真正的痛苦开始了!
正如其他人已经指出的那样,FreeAndNil本身也不错。 FreeAndNil函数没有被破坏/过时或类似的东西,它不会破坏你的代码。有人会争辩说,依赖FreeAndNil可能导致或表明设计缺陷。
我在局部变量上使用FreeAndNil EVEN。在局部变量上使用它似乎是POINTLESS,因为一旦退出过程变量就会消失。但是,这是一个好习惯,只会花费额外的几个字节。认为您可以在稍后的日期在程序结束时添加更多代码,在您释放对象的位置之后,代码将(显然意外地)尝试访问释放的对象。如果对象是NIL,BABUM,即时AV(example) 注意:有些人可能会说他们从未访问过免费对象(基本上意味着他们从不犯错误),所以在这种情况下他们不需要FreeAndNil。好吧,我不是机器人。我做错了。
一些保守的人可能会说这个简单的调用会浪费RAM和CPU资源。我永远不会说保存内存/ CPU很糟糕。我也喜欢提供小型/快速/单片应用程序!但我不认为使用FreeAndNil删除会浪费超过几个字节和CPU周期(几乎没有)。它不会对日常生活产生真正的影响,特别是当您认为像TButton字形或程序图标这样的图形资源可以占用50-300KB时,您的程序可以包含数十个这样的图形资源。
赞成
Mason Wheeler已经指出了一篇文章,该文章展示了使用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
但是Embarcadero决定删除那篇文章,所以一定有什么问题。
作为结论,此时,我们没有一段CONCRETE(和可编译的)代码来表明FreeAndNil可能会造成伤害。 (对于那些反对FreeAndNil的人,请通过发布代码来启发我们。) 但是,我们确实有代码显示FreeAndNil如何保存我们的屁股。