Could QueryInterface() provide us with nullptr when succeed? [duplicate]

你离开我真会死。 提交于 2019-12-24 11:26:58

问题


Imagine a situation:

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

I wonder, if pControl could ever be nullptr inside last block {...}. The question occurred, because I saw that code:

if(SUCCEEDED(hr) && pControl)
{...}

I consider that part && pControl as a redundant one. Am I right?


回答1:


QueryInterface() is required to provide a valid (so non-null) interface pointer on success and a null pointer on failure. However you don't know whether some specific implementation follows that rule and the code you cite most likely tries to be defensive.

That said, the following

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

also calls QueryInterface() under the hood to retrieve the pointer to the requested interface. If the code wants to be defensive it should check that pGraph is non-null on success too.

The problem here is you don't know how bad it is when you get S_OK and a null pointer. Suppose QueryInterface() works like this (really bad code follows, not for use anywhere):

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
    }
}

great, the defensive code will avoid dereferencing a null pointer retrieved here together with S_OK returned but reference count will be incorrect - noone will have a chance to call matching Release(). So you instantiate such an object, then call QueryInterface() which works as above, the refcount is now 2, then you Release() the object once and it leaks. How bad it happens to turn out depends on a lot of factors.

Same with CoCreateInstance() - it calls the same QueryInterface() under the hood. Both may be broken and your mileage may vary both with and without checking the retrieved pointer against null.



来源:https://stackoverflow.com/questions/25325891/could-queryinterface-provide-us-with-nullptr-when-succeed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!