我们有一些使用COM的旧软件代码。我注意到,在某个地方,我们对IInspectable指针执行了queryInterface,但是不必费心调用release。
例如:
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
}
我将Release添加到上面的代码中,如下所示:
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;
但是我看到上面的代码在发行期间有时在上面的函数中崩溃。我发布界面的方式有问题吗?在Release语句之后,我可以确认在函数的其他任何地方都没有使用myInterface。
抱歉,无法复制/粘贴实际代码,但是上面的代码几乎总结了我正在调试的可疑代码。基本上,我想知道的是,在上述情况下,我需要调用Release()吗?这是调用Release()的正确地方/方法吗?我是否需要添加其他任何安全检查?
答案 0 :(得分:0)
在第一个foo
函数中,您不应调用myInterface->Release()
。对Release
的每次调用都应与引用一起配对。在该函数中,您无需执行myInterface->AddRef
,因此,如果添加myInterface->Release
,则您的函数会将引用计数减1,这似乎不是正确的行为。
从概念上讲,应该在函数进入时调用AddRef
,在函数退出时调用Release
。即使在COM中引用计数是“侵入性的”,建议的编码方式是将每个接口指针都视为具有其自己的引用计数。
这通常包装在智能指针类中。但是,当使用接收到原始“输入”接口指针的函数时,只需忽略函数中的这两个调用,并将该指针视为观察者指针,即可“优化”添加和释放。
对QueryInterface
的调用将隐式执行pObj->AddRef()
,但这与myInterface
无关。完成pObj
后,应该发生pObj->Release()
-但这是由ComPtr
包装器管理的,您不应该添加显式调用。