-4

我正在调试一段怀疑 com 对象内存泄漏的代码。代码结构如下:

一些方法:

  • 在 com smart ptr 中创建一个 com 对象的新实例。
  • 获取其接口指针 Addref 并将其添加到地图中。

析构函数:

  • 循环遍历地图并删除所有 com 对象。例如delete iptr

这显示为 umdh 工具输出中的可能泄漏。释放对象的正确方法应该是对该映射中的所有对象调用 release。

调用 delete 会有什么影响?

4

2 回答 2

4

你的意思是你只是简单地做指向 COM 接口的指针在delete ptr;哪里!?用于销毁使用创建的对象。这是唯一正确的用法。对于最初不是使用. 因此,除非您使用表达式自己创建了实现 COM 接口的对象,否则这样做会导致未定义的行为。正如您自己所说,COM接口必须通过调用方法来释放。这是释放 COM 接口的唯一正确方法……ptrdeletenewdeletedeletenewnewRelease()

考虑 COM 接口与对象不同的事实。同一个对象可以实现多个不同的COM接口,可以通过QueryInterface()方法查询。同一个接口也可以有多个引用。因此,并非每次调用都Release()必然会破坏对象或空闲内存……

于 2019-03-04T16:29:28.777 回答
0

唯一需要从类外部删除 COM 对象的情况是,如果您自己实现 IClassFactory,使用 new 为请求的对象分配内存,但请求的 IID 对象不支持。在这种情况下,引用计数仍然为零,您需要在返回之前删除(可以说是潜在的而不是实际的)COM 对象。那时它将是一个真正的 c++ 对象(在删除之前的 new 之后)但不是真正的 COM 对象,尽管所有外观,所有其他情况都应该使用 Release。

即使在那里,您也可以通过为 IID_IUnknown 调用 QueryInterface 并使用该接口指针来查询传递给 CreateInstance 的任何 IID 而不是直接使用类对象指针来使其成为真正的 COM 对象。如果您遵循该模式,所有删除都将通过 Release 方法(因为用于查询的 IUnknown 需要释放),并且不会有其他引用。

然而,自己实现 IClassFactory(甚至是 IUnknown)通常是愚蠢的,有很多框架(一个是 ATL)可以更容易地获得 COM(特别是聚合)的繁琐细节。

于 2019-03-04T16:55:04.947 回答