This question already has an answer here:
-
Handling CoCreateInstance return value
2 answers
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?
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.