COM 对象清理
Posted
技术标签:
【中文标题】COM 对象清理【英文标题】:COM Object Clean Up 【发布时间】:2011-01-21 04:20:18 【问题描述】:下面两行代码有什么区别:
CComPtr< IInterface > m_interface;
IInterface* m_interface;
我知道 CComPtr 有助于消除内存泄漏,但我得到的结果不一致。用CComPtr< IInterface > m_interface;
声明指针时
并且在我的 C# 代码中使用该接口没有错误,但是在 VC++ 中使用该接口我得到一个未处理的异常错误,即使我注释掉 IInterface 的实例创建。
我很确定问题出在某个地方:
STDMETHODIMP CSomeClass::get_IClass(IClass** var)
return m_class_var->QueryInterface(var);
STDMETHODIMP CSomeClass::putref_IClass(IClass* var)
m_class_var = var;
return S_OK;
当我声明接口指针时:IInterface* m_interface;
我在 C# 中测试接口时收到 RPC_E_SERVERFAULT 错误,并且必须显式调用 GC.Collect() 以避免在实例化一些对象后引发错误。在 VC++ 中测试接口时,错误是一致的,但发生的时间不同。如果我注释掉 IInterface 的实例创建,代码运行良好,但是当我尝试创建一个实例时,我得到与以前相同的错误,只是一个模糊的未处理异常错误。我在这里做错了什么?
【问题讨论】:
你真的应该花 15 分钟制作一个很短的 sn-p 来证明问题。 你说“在 VC++ 中使用接口我得到一个未处理的异常错误”——你能告诉我们在 VC++ 中使用接口的代码吗? 【参考方案1】:CComPtr
是一个智能指针,设计用于在与 COM 惯用语一起使用时做“正确”的事情。
get_IClass
的代码看起来不错,但在存储 putref_IClass
时需要在 IClass
上调用 AddRef
。如果你使用CComPtr
,那会自动发生。
您需要添加有关 VC++ 未处理异常的更多详细信息。
【讨论】:
谢谢。这有助于更好地理解。我会投票给你,但我没有足够的声望点【参考方案2】:IInstance* m_instance
是一个指向 IInstance 对象的简单指针。您必须自己管理此指针的生命周期。不像普通对象那样new
和delete
COM 对象。相反,操作系统会在您调用 WINAPI 函数 `CoCreateInstance' 时分配对象:
// instantiate the CoClass which implements IInstance...
IInstance* instance = 0;
HRESULT hr = CoCreateInstance(__uuidof(mylibrary::MyCoClass), 0, CLSCTX_INPROC_SERVER, __uuidof(mylib::IInstance), &instance);
: :
// We're done, so release the object...
instance->Release();
instance = 0;
每个 COM 对象都实现了引用计数。当对象的最后一个引用是Release()
ed 时,COM 对象会自行销毁。
使用CComPtr<>
可以简化您管理COM 对象生命周期的方式。它是本质上类似于 std::auto_ptr 或 Boost 的 shared_ptr 的智能指针,但它适用于 COM 对象。通常,在使用 CComPtr 时,您将调用 CreateInstance
成员函数而不是调用 WINAPI 函数,并且在完成后您不会显式调用 Release
。只要让 CComPtr 超出范围,当它的析构函数被调用时,它会为你调用Release
:
void function()
// instantiate the CoClass which implements IMyInterface...
CComPtr<IInstance> instance;
instance.CoCreateInstance(__uuidof(mylibrary::MyCoClass));
: :
// We're done, so release the object...
// dont have to do anything, it will be released when function() exits
【讨论】:
【参考方案3】:CComPtr
第一个将在超出范围时调用其析构函数,我认为(自从我使用它很长时间以来)它会自动调用 m_interface ->Release()。
后者是指向接口的指针,你必须在调用 m_interface->Release() 时进行管理。
你能确认COM对象在访问之前没有被释放吗?
【讨论】:
谢谢。我已经编辑了我的问题以提供更多信息。我在 VC++ 代码测试接口实现中调用 Release()。它没有帮助,我怀疑即使在使用 CComPtr以上是关于COM 对象清理的主要内容,如果未能解决你的问题,请参考以下文章