有没有办法确定我们对某个对象持有一个可用的引用,即确定它尚未被释放而留下该非零引用悬空。
答案 0 :(得分:6)
如果您使用FastMM4作为内存管理器,则可以检查该类是否不是 TFreeObject 。
或者,在更标准的情况下,使用一个例程,通过检查类VMT 来验证您的对象是否正如它所说的那样。
有这样的ValidateObj函数已经存在了一段时间(由Ray Lischner和Hallvard Vassbotn撰写:http://hallvards.blogspot.com/2004/06/hack-6checking-for-valid-object.html)
这是另一个:
function ValidateObj(Obj: TObject): Pointer;
// see { Virtual method table entries } in System.pas
begin
Result := Obj;
if Assigned(Result) then
try
if Pointer(PPointer(Obj)^) <> Pointer(Pointer(Cardinal(PPointer(Obj)^) + Cardinal(vmtSelfPtr))^) then
// object not valid anymore
Result := nil;
except
Result := nil;
end;
end;
更新:有点谨慎......上面的函数将确保结果是nil或有效的非nil对象。如果内存管理器已经重新分配了以前释放的内存,它并不能保证Obj仍然是你认为的那样。
答案 1 :(得分:3)
没有。除非您使用引用计数或垃圾收集器之类的东西,以确保在零引用之前不会释放任何对象。
如果您使用接口,Delphi可以为您做引用计数。当然Delphi for .Net有一个行李收集器。
如前所述,您可以使用Delphi的知识或内存管理器内部来检查有效的指针或对象,但它们并不是唯一可以指向您的指针。因此,即使使用这些方法,也无法覆盖所有指针。并且你的指针也有可能再次有效,但是给了其他人。所以它不是你要找的指针。你的设计不应该依赖它们。使用工具检测您所做的任何参考错误。
答案 2 :(得分:1)
标准,不......
这就是为什么VCL组件可以注册自己以通知对象的销毁,以便他们可以从内部组件列表中删除引用,或者只是重置其属性。
因此,如果您想确保没有任何无效的引用,则有两种选择:
答案 3 :(得分:1)
正如其他人所说,没有明确的方法,但如果你很好地管理所有权,那么FreeAndNil例程将确保你的变量是零,如果它没有指向任何东西。
答案 4 :(得分:1)
无论如何检查引用是否有效通常不是一个好主意。如果引用无效,则程序将在使用无效引用的位置崩溃。否则,无效引用可能会存活更长时间并且调试变得更难。
以下是一些为什么最好崩溃无效引用的参考。 (他们谈论Win32中的指针,但这些想法仍然相关):
答案 5 :(得分:0)
不幸的是,除了通过精心编写正确的代码之外,没有办法100%保证指向任何东西的指针仍然有效。
答案 6 :(得分:0)
使用接口引用(而不是对象引用)可以避免这些无效指针问题,因为代码中没有显式调用Free。