This question already has answers here:
Handling CoCreateInstance return value

(2个答案)


6年前关闭。




想象一个情况:
CComPtr<IGraphBuilder> pGraph;
HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));
if (SUCCEEDED(hr))
{
    CComPtr<IMediaControl> pControl;
    hr = pGraph->QueryInterface(IID_PPV_ARGS(&pControl));
    if(SUCCEEDED(hr))
    {...}
}

我想知道pControl在最后一个块{...}中是否可以为nullptr。发生问题了,因为我看到了以下代码:
if(SUCCEEDED(hr) && pControl)
{...}

我认为那部分&& pControl是多余的。我对吗?

最佳答案

QueryInterface()是必需的,以便在成功时提供有效的(所以非null)接口(interface)指针,而在失败时提供null指针。但是,您不知道是否有某些特定的实现遵循该规则,您引用的代码很可能会起到防御作用。

也就是说,以下

HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL,
    CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&pGraph));

还可以在后台调用QueryInterface()来检索指向所请求接口(interface)的指针。如果代码想要防御,也应该在成功时检查pGraph是否为非空。

这里的问题是当您获得S_OK和空指针时,您不知道它有多糟。假设QueryInterface()的工作方式如下(的代码确实很糟糕,不适用于的任何地方):
HRESULT TheClass::QueryInterface( REFIID iid, void** ppv )
{
    if( iid == SomeSpecificIID ) {
        AddRef();
        *ppv = 0; //BAD IDEA, BAD CODE, JUST DON'T
        return S_OK;
    } else {
       //whatever
    }
}

很好,防御代码将避免将在此处检索到的空指针与返回的S_OK一起取消引用,但引用计数将不正确-没有人将有机会调用匹配的Release()。因此,您实例化了这样一个对象,然后调用QueryInterface(),它的工作原理与上面相同,引用计数现在为2,然后对对象进行Release()一次,然后泄漏。结果有多糟糕取决于许多因素。

CoCreateInstance()相同-在后台调用相同的QueryInterface()。无论是否检查检索到的指针是否为null,两者都可能损坏,并且里程可能会有所不同。

关于c++ - 成功时,QueryInterface()可以为我们提供nullptr吗? ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25325891/

10-09 06:01