COM Memory Leak

Don’t Get Caught Off Guard



COM Memory Leak

Don t Get Caught Off Guard


By Alvin Bruney


I recently ran into a nasty memory leak that caught me off guard and I d like to share my experience with you. Take a look at this C++ .NET COM Interop code (this is actual production code, so variable names have been changed to protect the innocent):


//house keeping


IDisposable *pIDisposable;

char szBufMsg[256];

//call into COM

hr = ((IPointerInterface*)pIPointer)->QueryInterface(IID_IDisposable,


//do some stuff here


//start clean-up

hr = pIDisposable->Dispose();

Code Snippet 1: Managed C++ code in action.


I ve removed the code checks on the HRESULT value to keep the example uncluttered, but take my word for it that the proper checks (as well as exception handling code) were in place. Also, note that dispose is called appropriately. So, why does the code still leak memory?


When you use an interface pointer, that pointer also holds a live reference to the COM object. As you start marking the object eligible for collection by calling dispose, the reference count on the COM object may not reach zero because the object is still reachable and is therefore not garbage.


With at least one live reference, resource de-allocation cannot occur. The COM object cannot be cleaned up because there is still a live reference keeping the reference count above zero.


By strict definition, this is not a memory leak. From the CLR s perspective, the runtime sees a valid root for the object that is reachable through the interface pointer. From your code s perspective, it is a memory leak. The code was finished using the object and started doing clean-up with the assumption that the COM object would go away. Whose fault is it? Actually, the end-user doesn t care. All they see is a server application that is failing.


That said, the fix is simple; release the interface pointer after you call dispose. Here is the updated code:


//do some stuff here


//start clean-up

hr = pIDisposable->Dispose();

//add the release call to ensure memory is released correctly


Code Snippet 2: Code releasing all resources.


As with other memory leaks, this one is especially difficult to detect; you can t really fault the programmer for not knowing this, right? The typical fix of calling GC.Collect all day will not help you here because, from the runtime s perspective, the COM object is still reachable.


This particular issue bubbled up to my attention when production servers started exhausting memory and failing. There are many good articles on the Web that explain in detail exactly how to find and fix memory leaks, so I won t outline them here. Suffice it to say that all it really takes is a shady character such as pIPointer holding onto resources inappropriately to bring a production server to its knees. And that s never a pleasant experience!


Alvin Bruney is a Technology Specialist working for Royal Bank of Canada in the .NET Centre of Excellence program. He is a Microsoft Press author and a long-time ASP.NET MVP.





Hide comments


  • Allowed HTML tags: <em> <strong> <blockquote> <br> <p>

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.