代码之家  ›  专栏  ›  技术社区  ›  a.delphi.developer

对已释放对象的错误引用

  •  6
  • a.delphi.developer  · 技术社区  · 17 年前

    有没有办法确保我们持有一个对某个对象的可用引用,也就是说,确保它还没有被释放,而非零引用仍然悬空。

    7 回复  |  直到 17 年前
        1
  •  6
  •   Francesca    17 年前

    如果您使用FastMM4作为内存管理器,可以检查该类是否不可用 TFreeObject
    或者,在一个更标准的情况下,使用一个例程来验证您的对象是否是它所说的对象 .

    有这样的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仍然是您认为的那样。

        2
  •  3
  •   Lars Truijens    17 年前

    不可以。除非您使用引用计数或垃圾收集器之类的方法来确保没有对象在引用为零之前被释放。

    如果您使用接口,Delphi可以为您进行引用计数。当然,Delphi for.Net有一个gargage收集器。

    如前所述,您可以使用Delphi的knowledege或内存管理器内部来检查有效的指针或对象,但它们并不是唯一可以为您提供指针的工具。因此,即使使用这些方法,也无法覆盖所有指针。还有一种可能性是,你的指针碰巧再次有效,但却给了其他人。因此,它不是您要寻找的指针。您的设计不应该依赖于它们。使用工具来检测您所做的任何引用错误。

        3
  •  1
  •   Davy Landman    17 年前

    标准,不。。。

    这就是为什么VCL组件可以注册自己以获得对象销毁的通知,这样它们就可以从组件的内部列表中删除引用,或者只是重置它们的属性。

    因此,如果您想确保没有任何无效引用,有两种选择:

    • 实现每个类都可以订阅的销毁通知处理程序。
    • 修复代码时,引用不会通过不同的对象散布。例如,您只能通过另一个对象的属性提供对引用的访问。而不是将引用复制到私有字段,而是访问另一个对象的属性。
        4
  •  1
  •   mj2008    17 年前

        5
  •  1
  •   Otherside    17 年前

    不管怎样,检查引用是否有效通常不是一个好主意。如果引用无效,程序将在使用无效引用的位置崩溃。否则,无效引用可能会存活更长时间,调试变得更困难。

    以下是一些关于为什么在无效引用上崩溃更好的参考。(他们谈论Win32中的指针,但这些想法仍然相关):

        6
  •  0
  •   Lasse V. Karlsen    17 年前

        7
  •  0
  •   mjn anonym    15 年前

    使用接口引用(而不是对象引用)可以避免这些无效指针问题,因为代码中不再显式调用Free。