【问题标题】:How do I tell if I'm leaking COM objects?如何判断我是否泄漏了 COM 对象?
【发布时间】:2011-04-20 04:07:33
【问题描述】:

我正在编写一些(相对简单)使用 COM 的代码,在某些对象上调用 AddRef() 并稍后对它们执行 Release()。除了彻底检查代码之外,还有什么方法可以检查我是否到处泄漏 COM 对象?

(我不能使用引用计数IBlahBlahPtrs,因为我需要将对象传递给一组不知道 COM 是什么的 API,因此不了解整个“引用计数指针” thingy - 他们像令牌一样传递指针。)

谢谢!

【问题讨论】:

  • 听起来您传递 COM 指针的 API 不知道它们是 COM 指针,因此不调用 IUnknown 函数。如果是这样,您难道不能在您自己的代码中继续使用 IBlahBlahPtr 对象并将指针值传递给 API(并围绕从这些 API 返回的指针实例化新的 IBlahBlahPtr 对象)吗?
  • 我们试图在几个简单的函数中公开 COM API(在本例中为 MSXML)的功能。例如,我们的“创建 XML 文档”函数需要返回实际上是一个 IXMLDOMDocument *,但就调用者所知,它只是一个以实现定义的方式标识文档的标记。相同的 API 将在 OS X 上重新实现,其中 COM 甚至不是一个东西,它会返回一个类似的特定于平台的令牌。

标签: c++ winapi com


【解决方案1】:

这与检查任何 C 或 C++ 代码中的泄漏没有什么不同。使用<crtdbg.h> 检测泄漏,MSDN 库文章is here。如果没有足够的 IUnknown::Release() 调用,您将收到类工厂的泄漏报告。

引用计数接口指针是一个硬 COM 要求,你不能只是耸耸肩。如果客户端代码不这样做,那么在传递指向该代码的指针之前,您必须自己处理它。知道指针何时不再使用当然是一个更棘手的问题。

【讨论】:

  • 听起来好像提问者没有实现 COM 服务器,而只是使用 COM 对象。所以堆检查不会解决问题。此外,听起来提问者并没有“摆脱” COM 指针管理的责任(“除了真正彻底地检查代码......”)。
  • 是的,可以。如果服务器不可调试,节目就结束了。是的,检查非常彻底。当然还有单元测试。
【解决方案2】:

如果您使用 CrtDebug DEBUG_NEW 分配对象,您将在退出时自动转储所有泄漏的对象(基本上是所有未释放的内存),以及文件名和内存所在的行已分配。

【讨论】:

  • 我对 Hans Passant 的评论同样适用于 DEBUG_NEW;如果提问者的堆不是实际分配 COM 对象的堆,那么这种技术将无济于事。
  • 当然,他必须使用 DEBUG_NEW 构建 com 库。查看原始问题的 cmets,我看到他正在尝试使用 MSXML——所以他能否构建自己的这些库版本是值得怀疑的。
【解决方案3】:

根据我们在 cmets 中的对话,我认为您可以执行以下操作:

  • 使用智能指针(即IBlahBlahPtr)在您自己的代码中创建和管理 COM 对象。
  • 维护一组智能指针,代表调用者对您向上传递的指针的引用。每次将新的 COM 指针交给调用者时,将其智能指针放入集合中。
  • 如果您的调用者以某种方式放弃了 COM 指针(例如,通过某种“释放”函数向您传递 COM 指针令牌),则在集合中查找其智能指针并将其删除。如果该智能指针(表示调用者对对象的现已失效的引用)是该对象上唯一剩余的引用计数持有者,则将根据需要进行销毁。
  • 如果您的调用者以非放弃方式向您传递 COM 指针,您可以在调用期间围绕原始指针值包装一个新的智能指针对象,以便您在自己的代码中使用智能指针是一致的。多个智能指针可以引用同一个 COM 对象。

【讨论】:

    【解决方案4】:

    各种工具将为您检查。 BoundsChecker 可以。我认为,但不是 100% 肯定,AppVerifier 确实如此(它具有免费的额外好处)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-23
      • 2014-08-09
      • 2011-11-15
      • 2012-11-11
      • 2015-06-21
      • 1970-01-01
      • 2012-12-03
      • 1970-01-01
      相关资源
      最近更新 更多