Free和FreeAndNil之间的基本区别是什么?
FreeAndNil = Free + Nil吗?
何时应该使用Free,何时应该使用FreeAndNil?
Free和FreeAndNil之间的基本区别是什么?
FreeAndNil = Free + Nil吗?
何时应该使用Free,何时应该使用FreeAndNil?
请参考以下实现:
看一下这个实现:
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
,以便bm
不再指向对象曾经存在但现在不存在的位置。这样你(和像assigned
这样的例程)就不会被欺骗认为还有一个位图对象。FreeAndNil(foo)
而不是foo.Free
。好的,为什么不呢?额外的指令foo := nil
可能不会花费太多的纳秒级执行时间,而且确实assigned(foo) = false
是一个被释放对象的非常好的属性。但是反过来,如果你知道自己在做什么,并且知道在释放后永远不会再次使用foo
对象,那么你可以坚持只使用foo.free
。事实上,有人认为,在许多情况下(但并非所有情况),尝试使用已释放对象的变量本身就是一个错误。(当然,有些情况下你会故意这样做 - 你有一个有时被分配的对象foo
,有时不被分配。)foo.Free
之后将foo
设置为nil
是否必要,我认为这只是纠缠小节、吹毛求疵,并且非常接近荒谬。我无法想象有任何一种情况不正确地清理资源是有意义的,至少也应该具有一些意义。对于那些认为这是值得注意甚至讨论的问题的人,请坚定自己的立场,放弃Delphi或任何其他高级语言并且坚持使用汇编语言。 - Semanino请参阅Delphi Memory Management Made Simple,以获取我发现它有用的示例。底部的Mghie评论也值得阅读。
我会用另一种方式回答。
也许,在释放对象后用 nil
来填充对象引用并不总是一个好主意。
这样,您无法区分从未使用过的引用(因此为 nil
)和已被使用但将来不应再使用的引用。
因此,将其填充为特殊数字(类似于 FastMM 内存管理器在释放内存块的内容时可以执行的操作)。
--jeroen
Free
和FreeAndNil
之间的区别在于,在释放对象使用的内存的同时,FreeAndNil
还将对象引用设置为null。如果想要了解关于使用Free或FreeAndNil的讨论,请查看以下链接:
事实 vs 观点
有人会争辩说依赖 FreeAndNil 可能会导致或表明设计缺陷,但是他们无法以任何方式证明这一点。这只是他们的个人观点。另一方面,一个因为你拒绝使用 FreeAndNil 而随机崩溃并且无法调试的程序是一个事实而不是观点。
连在本地变量上都要用吗?
我甚至在本地变量上也使用 FreeAndNil。在本地变量上使用它似乎是毫无意义的,因为该变量在退出过程时就消失了。
想象一下,你可能在稍后的时间添加更多代码到过程的结尾,在释放对象的位置之后;该代码将(意外)尝试访问已释放的对象。如果对象为 NIL,则会立即发生 AV 错误(example)。
当你考虑到单个图形资源(如TButton图标或程序图标)可以占用50-300KB(而且你的程序可能有数十个这样的资源)时,争论FreeAndNil“浪费”的资源是毫无意义的。
神 vs 程序员缺点
没有实际/可靠的证据。
Allen Bauer有一篇文章,名为当FreeAndNil成为你的敌人时的案例,建议在非常特殊的情况下(视觉组件的析构函数)使用FreeAndNil可能会有问题。该文章中没有任何可编译的代码,只有一些可能导致问题的情况。
Allen指出应该用更好的方法替换FreeAndNil。例如使用FastMM。
然而,这个讨论展示了(通过可编译的代码)FastMM失败了,而FreeAndNil挽救了全局。
证据在哪里?
此时此刻,我希望有一个具体的/可编译的代码片段来证明FreeAndNil可能会造成伤害。
另一方面,我们确实有很多例子(见链接),说明FreeAndNil可以拯救我们的生命。
对于那些反对FreeAndNil的人,请通过发布一些可编译的代码来启发我们。