释放COM接口的正确方法
我们有一些使用COM的遗留软件代码。我注意到,在一个地方,我们对IInspectable指针执行queryInterface,但不用麻烦调用release 例如:释放COM接口的正确方法,com,c++-winrt,Com,C++ Winrt,我们有一些使用COM的遗留软件代码。我注意到,在一个地方,我们对IInspectable指针执行queryInterface,但不用麻烦调用release 例如: void foo(IInspectable* myInterface) { ComPtr<OBJTYPE> pObj; auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj); if (hr != S_OK)
void foo(IInspectable* myInterface)
{
ComPtr<OBJTYPE> pObj;
auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
if (hr != S_OK)
{
return hr;
}
//some code that uses pObj
}
void foo(IInspectable*myInterface)
{
ComPtr pObj;
auto hr=myInterface->QueryInterface(uuuidof(SomeType),&pObj);
如果(hr!=S_正常)
{
返回人力资源;
}
//一些使用pObj的代码
}
我在上述代码中添加了以下版本:
auto hr = myInterface->QueryInterface(__uuidof(SomeType),&pObj);
if (hr != S_OK)
{
return hr;
}
myInterface->Release(); //<-- Is this the correct way to release ?
//some code that uses pObj;
auto hr=myInterface->QueryInterface(uuu-uuidof(SomeType),&pObj);
如果(hr!=S_正常)
{
返回人力资源;
}
myInterface->Release()// 在第一个foo
函数中,不应调用myInterface->Release()。每次调用Release
都应该添加一个引用。在该函数中,您不需要执行myInterface->AddRef
,因此如果您添加myInterface->Release
,那么您的函数会将引用计数减少1,这似乎不是正确的行为
从概念上讲,您应该在进入函数时调用AddRef
,在退出函数时调用Release
。即使引用计数在COM中是“侵入式”的,建议的编码风格是将每个接口指针视为具有自己的引用计数
这通常包含在智能指针类中。但是,当使用接收原始“in”接口指针的函数时,可以通过省略函数中的这两个调用并将指针视为观察者指针来“优化”此添加和释放
调用QueryInterface
将隐式执行pObj->AddRef()
,但这与myInterface
无关。当您完成pObj
apObj->Release()
时,应该会发生,但这是由ComPtr
包装器管理的,您不应该添加显式调用。似乎是WRL的一部分,而不是C++/WinRT。ComPtr
析构函数将为您调用Release
。显式调用它将导致双重删除错误。由于您将myInterface
作为普通指针传递,这意味着接口上没有所有权转移;这是一个非所有者指针。您只负责OBJTYPE
接口,而ComPtr
为您负责。Microsoft::WRL::ComPtr
是一个COM智能指针,与ATL的CComPtr
非常相似。您不需要显式地调用Release
,因为智能指针会为您这样做。看见C++/WinRT有一个类似的WinRT::com_ptr
可以用来代替WRL。“但这与myInterface
”有点牵强。在绝大多数情况下,对QueryInterface
的调用将返回一个指针,指向与被调用方相同的对象实现的接口。我相信撕下的接口是唯一的例外。引用计数是按对象进行的,而不是按接口进行的。@IInspectable请看我的第二段。我并不反对这一点,只是最后一段偏离了概念思维,并做出了一个通常是错误的陈述。我不确定那一段是应该改写,还是完全删除。它没有像写的那样增加多少价值。