Windows Vista: "Memory Leak" when using Audio API notification routines

We recently got an internal report from someone using the internal audio notification APIs that they were leaking memory and they wanted to help from us debugging the problem. I took a look and discovered that the problem was a circular reference that was created when they called: CFoo::Initialize() { hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, […]

We recently got an internal report from someone using the internal audio notification APIs that they were leaking memory and they wanted to help from us debugging the problem.

I took a look and discovered that the problem was a circular reference that was created when they called:

CFoo::Initialize() { hr = CoCreateInstance(__uuidof(MMDeviceEnumerator), NULL, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), (void**)&m_pEnumerator); if (FAILED(hr)) return hr; if (FAILED(m_pEnumerator->RegisterEndpointNotificationCallback(this))); } CFoo::~CFoo() { m_pEnumerator->UnregisterEndpointNotificationCallback(this); }

The root cause of the problem is that the IMMDeviceEnumerator::RegisterEndpointNotificationCallback takes a reference to the IMMNotificationClient object passed in. This shouldn't be a surprise, because the Counted Pointer design pattern requires that every time you save a pointer to an object, you take a reference to that object (and every interface that derives from IUnknown implements the Counted Pointer design pattern). Since the RegisterEndpointNotificationCallback saves it's input pointer for later consumption (when it generates the notification), it has to take a reference to the object.

At the heart of the problem is the fact that CFoo object only calls UnregisterEndpointNotificationCallback in its destructor (which will never be called). If the CFoo object had a "Shutdown()" or other form of finalizer, the call to UnregisterEndpointNotificationCallback could be moved to the finalizer, thus removing the circular reference and avoiding the memory leak. This is by far the best solution - I'm a huge fan of deterministic finalism.

Full Article

Microsoft, Windows Vista, Memory, Memory Leak, Audio, API, Troubleshooting, Tips and Tricks, Knowledgebase