2

我们有一些使用 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() 的正确位置/方式吗?我是否需要添加任何其他安全检查?

4

1 回答 1

1

在第一个foo函数中,您不应该调用myInterface->Release(). 每次调用Release都应与添加引用配对。在那个函数中你不这样做myInterface->AddRef,所以如果你添加,myInterface->Release那么你的函数会将引用计数减一,这似乎不是正确的行为。

从概念上讲,您应该AddRef在函数的入口和函数Release的退出时调用。尽管引用计数在 COM 中是“侵入式的”,但推荐的编码风格是将每个接口指针视为具有自己的引用计数。

这通常包含在智能指针类中。但是当使用一个接收原始“in”接口指针的函数时,可以通过忽略函数中的这两个调用并将指针视为观察者指针来“优化”这个 Add 和 Release。


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

于 2018-09-25T07:13:34.270 回答