我正在调试一段怀疑 com 对象内存泄漏的代码。代码结构如下:
一些方法:
- 在 com smart ptr 中创建一个 com 对象的新实例。
- 获取其接口指针 Addref 并将其添加到地图中。
析构函数:
- 循环遍历地图并删除所有 com 对象。例如
delete iptr
这显示为 umdh 工具输出中的可能泄漏。释放对象的正确方法应该是对该映射中的所有对象调用 release。
调用 delete 会有什么影响?
我正在调试一段怀疑 com 对象内存泄漏的代码。代码结构如下:
一些方法:
析构函数:
delete iptr
这显示为 umdh 工具输出中的可能泄漏。释放对象的正确方法应该是对该映射中的所有对象调用 release。
调用 delete 会有什么影响?
你的意思是你只是简单地做指向 COM 接口的指针在delete ptr;
哪里!?用于销毁使用创建的对象。这是唯一正确的用法。对于最初不是使用. 因此,除非您使用表达式自己创建了实现 COM 接口的对象,否则这样做会导致未定义的行为。正如您自己所说,COM接口必须通过调用方法来释放。这是释放 COM 接口的唯一正确方法……ptr
delete
new
delete
delete
new
new
Release()
考虑 COM 接口与对象不同的事实。同一个对象可以实现多个不同的COM接口,可以通过QueryInterface()
方法查询。同一个接口也可以有多个引用。因此,并非每次调用都Release()
必然会破坏对象或空闲内存……
唯一需要从类外部删除 COM 对象的情况是,如果您自己实现 IClassFactory,使用 new 为请求的对象分配内存,但请求的 IID 对象不支持。在这种情况下,引用计数仍然为零,您需要在返回之前删除(可以说是潜在的而不是实际的)COM 对象。那时它将是一个真正的 c++ 对象(在删除之前的 new 之后)但不是真正的 COM 对象,尽管所有外观,所有其他情况都应该使用 Release。
即使在那里,您也可以通过为 IID_IUnknown 调用 QueryInterface 并使用该接口指针来查询传递给 CreateInstance 的任何 IID 而不是直接使用类对象指针来使其成为真正的 COM 对象。如果您遵循该模式,所有删除都将通过 Release 方法(因为用于查询的 IUnknown 需要释放),并且不会有其他引用。
然而,自己实现 IClassFactory(甚至是 IUnknown)通常是愚蠢的,有很多框架(一个是 ATL)可以更容易地获得 COM(特别是聚合)的繁琐细节。