删除com接口指针的效果

时间:2019-03-04 16:26:52

标签: c++ comobject com-interface

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

某些方法:

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

析构函数:

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

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

调用删除会产生什么影响?

2 个答案:

答案 0 :(得分:4)

您的意思是只做delete ptr;,其中ptr是指向COM接口的指针! delete用于销毁使用new创建的对象。那是delete的唯一正确用法。通常,delete并非使用new原本创建的任何内容都是无效的。因此,除非您使用new表达式创建了自己实现COM接口的对象,否则将导致未定义的行为。就像您自己说的那样,必须通过调用Release()方法来释放COM接口。那是放开COM接口的唯一正确方法……

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

答案 1 :(得分:0)

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

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

但是,自己亲自实现IClassFactory(甚至IUnknown)通常很愚蠢,那里有很多框架(其中一个是ATL),使正确处理COM(特别是聚合)的细节变得非常容易。