Why is a QueryInterface()
call always followed by a Release()
call? For example, I have seen a sample code from MSDN as below:
HRESULT hr = S_OK;
CDecoder *pObj = new CDecoder(&hr);
if (SUCCEEDED(hr))
{
*ppv = NULL;
hr = pObj->QueryInterface(riid, ppv);
}
pObj->Release();
return hr;
can someone explain the intent behind Release()
call here?
It's not always followed directly like this, though that is pretty common.
COM objects are reference counted. When you initially create the object, you get a pointer to an IUnknown
. Then you obtain some other interface with QueryInterface
. Since you (usually) don't care about the IUnknown
interface anymore, you release that. When you release the other interface you obtained, the reference count will be 0 so the object can be destroyed. If you don't release the IUnknown
, however, the reference count will stay non-zero, so the object can't be destroyed.
The most obvious case where you would not immediately release the IUnknown
is when/if you need to get more than one other interface. In such a case, you'd get the IUnknown
, then the second and third interfaces before releasing the IUnknown
. There are at least potentially cases where you might not know the third (or subsequent) interfaces right after you created the object either, so you might need to retain access to the IUnknown
for some arbitrary length of time before releasing it.
Why is a QueryInterface call is always followed by a Release call?
Because QueryInterface will call AddRef which increases the reference count to the pointer. When there are 0 references to a pointer it is freed for you.
Note: There is some confusion in this question's answers about what QueryInterface
actually does. It simply retrieves pointers to the supported interfaces on an object and increments the reference count on that object. It doesn't create a new object for each interface that it implements.
For example if you have an object which implements 2 interfaces, then the call would simply cast that object as each of the interface and increment a variable which is used as the reference count.
Note: The reference counting can be implemented in different ways, but the above explains the usual scenario. In particular @Ben describes a tear off interface below which stresses the importance of calling Release on the interface pointer that was returned to you.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With