当指针超出范围时,由 CComObject::CreateInstance 创建的 COM 对象不会被销毁

Posted

技术标签:

【中文标题】当指针超出范围时,由 CComObject::CreateInstance 创建的 COM 对象不会被销毁【英文标题】:COM object created by CComObject::CreateInstance not destroyed when pointer goes out of scope 【发布时间】:2014-10-25 19:42:21 【问题描述】:

使用智能指针CComObject 我通过调用它的静态方法CreateInstance 创建一个COM 对象。但是当我离开我的程序时,至少在 VS13 中,该对象仍然在运行。这是我的代码:

CComObject< CMyAtlObject > * myAtlCOMObject = NULL;
HRESULT hr = CComObject< CMyAtlObject >::CreateInstance(&myAtlCOMObject);
ASSERT(SUCCEEDED(hr));

我希望在超出范围时调用 ~CComObject() 方法,但这不会发生。

我尝试将上面的代码放在花括号中,以强制新创建的对象超出范围。 我尝试在myAtlCOMObject上调用FinalRelease并成功在myAtlCOMObject上手动调用Release,但程序在VS13中仍然没有停止运行。

我错过了什么?

【问题讨论】:

【参考方案1】:

这是带有内联 cmets 的代码:


  CComObject<CMyAtlObject>* myAtlCOMObject = NULL;
  HRESULT hr = CComObject< CMyAtlObject >::CreateInstance(&myAtlCOMObject);
  ASSERT(SUCCEEDED(hr));
  // NOTE: Created new object with reference count of ZERO
  
    const CComQIPtr<IMyAtlObject> pMyAtlObject = myAtlCOMObject;
    // NOTE: Reference count increased to ONE
  
  // NOTE: ~CComQIPtr went out of scope and called IUnknown::Release 
  //       decrementing counter to ZERO; decrement to zero causes destruction

// NOTE: There is no ~CComObject call here on myAtlCOMObject going out of scope
//       since myAtlCOMObject is a raw pointer

我错过了什么?

您缺少以下内容:

CreateInstance 创建一个新对象并获取原始指针,该指针在离开范围时不会自毁 CreateInstance 创建一个处于“不稳定”状态且引用计数为零的对象,它在引用管理上的自毁在某些东西至少增加一次引用计数然后将其减少到零之后开始;上面的CComQIPtr 就是一个例子

MSDN on CreateInstance:

返回的对象的引用计数为零,因此请立即调用 AddRef,然后在完成后使用 Release 释放对象指针上的引用。

你用什么代替CComObject::CreateInstance

我有一个helper template class CObjectPtr,它的行为方式类似于众所周知的CComPtr,并包装/管理本机 C++ 类。

我的代码是:

CObjectPtr<CFoo> pFoo;
pFoo.Construct(); // Instantiates automatically adding reference
CFoo* pRawFoo = pFoo; // Acts as a pointer
CComPtr<IFoo> pFooInterface = pFoo; // Good for exposing inmepleted interafaces
CObjectPtr<CFoo> pAnotherFoo = pFoo; // Same instance proper reference counting
// ~CObjectPtr releases reference, destroys the object on last release

此答案中还提供了另一个简单的包装器:How to better initialize a reference counter for a non-creatable COM object?。

【讨论】:

知道了。我现在可以退出我的 MFC 程序并且内存泄漏转储再次工作,因为 COM 对象已被正确释放。 不!如果您将CComQIPtr 与无论出于何种原因对象不支持的接口类型一起使用,您都会使对象泄漏。这里应该是CComPtr 这是正确的,我的代码 sn-p 在某种程度上简化了事情。如果接口已实现/可用,CComPtrCComQIPtr 都可以。否则CComPtr 宁愿导致编译器错误,而CComQIPtr 宁愿在运行时失败。我个人从不直接在真实代码上使用CComObject::CreateInstance 你用什么来代替 CComObject::CreateInstance?共创实例? @rtischer8277 大概CoCreateInstance 会出现在这段代码中。您正在实例化一个实现 COM 对象的 C++ 类,因此我假设此代码出现在您自己编写的类工厂中。

以上是关于当指针超出范围时,由 CComObject::CreateInstance 创建的 COM 对象不会被销毁的主要内容,如果未能解决你的问题,请参考以下文章

为啥共享指针在 main 末尾没有超出范围?

如何使智能指针在exit()时超出范围

当类的指针实例超出范围时不调用析构函数是真的吗?

超出范围时 UISearchController 未正确关闭 [重复]

超出范围后,在Lambda中设置共享指针

当变量超出范围时会发生啥?