COM对象清理

时间:2010-02-25 19:47:26

标签: c# c++ com activex components

以下两行代码有什么区别:

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的实例创建,代码运行正常,但是当我尝试创建实例时,我得到的错误与以前一样,只是一个模糊的未处理异常错误。我在这做错了什么?

3 个答案:

答案 0 :(得分:2)

CComPtr是一个智能指针,用于与COM习语一起使用时做“正确”的事情。

get_IClass的代码看起来不错,但putref_IClass需要在AddRef上调用IClass,因为您要存储它。如果您使用了会自动发生的CComPtr

您需要添加有关VC ++未处理异常的更多详细信息。

答案 1 :(得分:1)

IInstance* m_instance是一个指向IInstance对象的简单指针。您必须自己管理此指针的生命周期。您不像普通对象那样newdelete 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()时,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
}

答案 2 :(得分:0)

但是CComPtr&LT; IInterface&gt; m_interface是一个对象。而IInterface * m_interface是一个指针。

第一个会在超出范围时调用它的析构函数,我认为(自从我使用它以来很长时间)它会自动调用m_interface - &gt; Release()。

后者是指向接口的指针,你必须在调用m_interface-&gt; Release()时进行管理。

您可以确认在访问之前没有释放COM对象吗?