Detecting leaking COM objects is often a very hard task as the leak is caused by a mismatch in the number of AddRef() and Release() calls made to the COM object. Too many AddRef() calls and the object never gets released, resulting in a memory leak. Too many Release() calls and the object is destroyed before the intended point in the program, often resulting in an application crash at some point after the objects destruction.
To enable you to identify the reference counts of each object Memory Validator tracks calls to the AddRef() and Release() methods and displays the reference count for the object after the call.
Open the display settings dialog on the Memory tab and select the display of COM Reference Counts.
On the Collect tab of the settings dialog, select the collection of COM Reference Counting.
This tutorial will use the nativeExample.exe sample application to demonstrate memory leak detection. The nativeExample.exe application is shipped as a project with source code. The project can be found in the nativeExample directory in the same directory that Memory Validator was installed in. Please compile all configurations of the sample application before continuing the tutorial. The project file is nativeExample.dsp.
Windows 2000 and Windows XP
If you are building the sample application for use with Windows 2000 or Windows XP, you will need to define _WIN32_WINNT=0x0500 and WINVER=0x0500.
The example application does not use any COM objects. For the purposes of the example, we have created a C++ class that has methods AddRef() and Release() which return ULONG values. The class behaves in a similar manner to a COM object, in that when it is instantiated, its reference count is 1 and when it is destroyed is expects it’s reference count to be 1. The difference is that this is not a COM object. When have implemented the example like this so that you can follow the code easily without having to wade through the source code associated with a normal COM object. For the purposes of the example, the behaviour is the same.
When COM Reference Counting is enabled, any C++ class methods with the same function signature as:
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void __RPC_FAR *__RPC_FAR *ppvObject); ULONG STDMETHODCALLTYPE AddRef(); ULONG STDMETHODCALLTYPE Release();
will be tracked. This allows you to easily track your own reference counted objects (be they COM objects or not) using the COM Reference Counting functionality.
The example will create an object, increase the object’s reference count 3 times, call QueryInterface() asking for a specific interface, then decrement the object’s reference count 3 times, followed by destroying the object. The object will not leak. However, you will be able to see on the Memory tab of Memory Validator the reference counts increase, the call to QueryInterface() and the reference counts decrease.
Select [installdir]\nativeExample\debugNonLink\nativeExample.exe using the Browse… button. Accept all default settings and move through all pages of the wizard to the last page. Click the Start Application button.
exampleAddRefRelease *obj; DWORD rc; obj = new exampleAddRefRelease(); rc = obj->AddRef(); obj->doSomeWork(); rc = obj->AddRef(); obj->doSomeWork(); rc = obj->AddRef(); obj->doSomeWork(); void *output; rc = obj->QueryInterface(IID_IUnknown, &output); rc = obj->Release(); rc = obj->Release(); rc = obj->Release(); delete obj;