我正在调试一段代码,怀疑com对象中的内存泄漏。代码的结构如下所示:
某些方法:
析构函数:
delete iptr
这表示umdh工具输出中可能存在泄漏。释放对象的正确方法应该是在该映射中的所有对象上调用release。
调用删除会产生什么影响?
答案 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(特别是聚合)的细节变得非常容易。