Effect of Deleting a com interface pointer

548 Views Asked by At

I am debugging a piece of code suspecting memory leaks in com objects. Structure of the code is something like below:

Some method:

  • Create a new instance of a com object into com smart ptr.
  • Get its interface pointer, Addref and add it to a map.

Destructor:

  • loops through the map and deletes all com objects. E.g. delete iptr

This shows as probable leak in umdh tool output. The correct way to free the object should be to call release on all objects in that map.

What effect will calling delete have?

2

There are 2 best solutions below

0
On

You mean you simply do delete ptr; where ptr is the pointer to the COM Interface!? delete is for destroying objects that were created using new. That is the only correct use of delete. It's not a valid thing in general to delete anything that was not orignally created using new. So unless you created the object that implements the COM interface yourself using a new expression, doing so will result in undefined behavior. As you said yourself, COM interfaces have to be released by calling the Release() method. That is the only correct way to let go off a COM interface…

Consider the fact that a COM interface is not the same thing as an object. The same object can implement multiple different COM interfaces, which you can query via the QueryInterface() method. There can also be multiple references to the same interface. So not every call to Release() necessarily destroys an object or free memory to begin with…

0
On

The only time that delete should be needed on a COM object from outside the class is if you implement IClassFactory yourself, use new to allocate the memory for a requested object but an IID is requested that the object does not support. In that case the reference count will still be zero and you need to delete the (arguably potential rather than actual) COM object before returning. It would be a real c++ object at that point (after new before delete) but not a real COM object despite all appearances, all other cases should use Release.

Even there you could make it a real COM object by calling QueryInterface for IID_IUnknown and using that interface pointer to query for whatever the IID passed to CreateInstance was rather than directly using the class object pointer. And if you follow that pattern all deletes would be through the Release method (because the IUnknown used for the query would need releasing) and there would be no other references.

However implementing IClassFactory (or even IUnknown) yourself is generally silly, there are plenty of frameworks out there (ATL for one) that make getting the fiddly details of COM (aggregation in particular) right so much easier.