释放COM接口的正确方法

时间:2018-09-25 07:02:21

标签: 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)
    {
        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()的正确地方/方法吗?我是否需要添加其他任何安全检查?

1 个答案:

答案 0 :(得分:0)

在第一个foo函数中,您不应调用myInterface->Release()。对Release的每次调用都应与引用一起配对。在该函数中,您无需执行myInterface->AddRef,因此,如果添加myInterface->Release,则您的函数会将引用计数减1,这似乎不是正确的行为。

从概念上讲,应该在函数进入时调用AddRef,在函数退出时调用Release。即使在COM中引用计数是“侵入性的”,建议的编码方式是将每个接口指针都视为具有其自己的引用计数。

这通常包装在智能指针类中。但是,当使用接收到原始“输入”接口指针的函数时,只需忽略函数中的这两个调用,并将该指针视为观察者指针,即可“优化”添加和释放。


QueryInterface的调用将隐式执行pObj->AddRef(),但这与myInterface无关。完成pObj后,应该发生pObj->Release() -但这是由ComPtr包装器管理的,您不应该添加显式调用。