1

想象一个情况:

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是多余的。我对吗?

4

1 回答 1

1

QueryInterface()需要在成功时提供有效(非空)接口指针,失败时提供空指针。但是,您不知道某些特定实现是否遵循该规则,并且您引用的代码很可能试图防御。

也就是说,以下

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

还在后台调用QueryInterface()以检索指向所请求接口的指针。如果代码想要防御,它也应该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()两者都可能被破坏,并且无论是否检查检索到的指针是否为空,您的里程都可能会有所不同。

于 2014-08-15T12:27:34.317 回答