Detecting COM Reference Count Errors

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.

Memory Validator COM data collection settings

On the Collect tab of the settings dialog, select the collection of COM Reference Counting.

Memory Validator data collection settings

Sample Application

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.

Tracking COM Reference Counts

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.

  • Start your program using Memory Validator’s launch program option.Memory Validator launch toolbarThe launch application wizard displayed.

    Memory Validator launch wizard

    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.

  • On the Allocation menu, choose the AddRef/Release test option.
    The following code will be executed.

    	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;
    
  • Click Refresh on the Memory tab. The reference count actions will be shown.In this example you can see the reference count decrements match the reference count increases. Selecting a COM object highlights (in grey) all other calls to the same COM object.Memory Validator AddRef/Release results

Fully functional, free for 30 days