【问题标题】:Could QueryInterface() provide us with nullptr when succeed? [duplicate]QueryInterface() 可以在成功时为我们提供 nullptr 吗? [复制]
【发布时间】:2014-08-15 11:49:21
【问题描述】:

想象一种情况:

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)
{...}

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

【问题讨论】:

  • 根据 com 规范,这是多余的......但没有什么能阻止糟糕的编码器自己实现 QueryInterface 并让它给出一个空指针,所以也许这个版本提供了一点保护
  • 这种代码通常是一个非常糟糕的主意。但这取决于您愿意提供什么样的支持。如果您可以轻松地忽略“它不起作用”的支持请求,那么您将永远无法复制它,那么我想没关系。

标签: c++ com hresult nullptr queryinterface


【解决方案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()。两者都可能被破坏,并且无论是否检查检索到的指针是否为空,您的里程都可能会有所不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-08-20
    相关资源
    最近更新 更多