Delphi 对象、NIL 对象和接口(interface)

标签 delphi com interface null

我正在寻找有关如何调试在 Delphi VCL 中使用 MS XML 包装器的应用程序中的崩溃的提示。我怀疑内存损坏,或者对象和接口(interface)之间发生了某种晦涩难懂的邪恶事情,例如引用计数错误或堆损坏。实际上,问题是:如何调试此类崩溃?

此特定代码大量内部使用并扩展了基本 XmlIntf 接口(interface) (IXMLNode)。 ISomethingCustom 是扩展 IXMLNode 的接口(interface)。当我们在递归函数中的某个地方崩溃时,就会出现问题,该函数传递了一个 ISomethingCustom,该 ISomethingCustom 也是(或在接口(interface)方面也支持)IXMLNode。

   boolean UtilityFunction( aNode: ISomethingCustom ):Boolean;
   begin
      if not Assigned(aNode) then exit; // this works. great.
      if not Assigned(aNode.ParentNode) then exit; // this DOES NOT WORK.
     // code that blows up if aNode.ParentNode is not assigned.
   end;

情况是 aNode 也是 IXMLNode,并且分配了 IXMLNode.ParentNode 值(不是 nil),但它指向一个可能已被释放、销毁或以某种方式损坏的 COM 对象。我试图弄清楚当接口(interface)指针看似有效但其背后的对象已被某种方式破坏时发生了什么。

检查Assigned(aNode.ParentNode)会返回TRUE,即使您尝试在调试器中进行强制转换(仅在运行时,而不是在代码中),如下所示:

  1. 检查/评估节点
  2. 检查/评估 TInterfacedObject(aNode).ClassName (至少可以在 Delphi 2010 中运行!)
  3. 现在强制转换 TWhateverClassNameYouGotBefore(aNode)。
  4. 在调试器中我现在看到这是 NIL。这可能意味着 神奇的“施法界面”回到 对象”的新功能 delphi 2010,失败了。

我相信我正在尝试调试因引用计数问题而导致堆损坏或 COM 对象在堆上损坏的问题。

我真的认为任何人都不应该出现界面看似有效但底层对象已被删除的情况。我真的很想知道该怎么办,以及发生了什么事。

最佳答案

尽管您没有在代码中显示它,但您的注释似乎表明您正在将接口(interface)变量类型转换为类类型。这是不允许的。我已经描述了原因:

接口(interface)引用和对象引用并不指向相同的东西。因此,当编译器认为您有另一个方法时,调用其中一个方法会产生意外结果。您很不幸,因为代码继续运行,而不是因访问冲突而崩溃,这更能表明您做错了什么。

我上面的文章最后建议您使用 JCL 中的 JclSysUtils​.GetImplementorOfInterface 函数如果您有一个 Delphi 实现的接口(interface),并且该接口(interface)没有提供自己的功能来显示底层对象。

关于Delphi 对象、NIL 对象和接口(interface),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3678710/

相关文章:

Delphi GetHostByName 相当于 firemonkey?

android - 使用 Delphi 以编程方式检查 SD 卡是否可用

delphi - COM Elevation Moniker 在 Vista/Windows 7 下无法提升服务器

windows - 在 IDL 中将 IUnknown 派生接口(interface)标记为双重接口(interface)有什么意义吗?

java - 如果常量接口(interface)反模式是一种犯罪行为,那么 Swing 为什么要这样做呢?

c# - 有没有一种方法可以为一个接口(interface)编写测试,然后针对所有实现该测试的类对其进行测试?

C# 和德尔福。使用 C# 在 Delphi 中读取加密和压缩的 XML

delphi - 扫描文件夹/子文件夹/文件时如何减少CPU使用率?

c++ - 当指针超出范围时,CComObject::CreateInstance 创建的 COM 对象不会被销毁

java - 为什么应该首选 Java 类的接口(interface)?