October 25, 2007
3:07 pm

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

Loading

Contextual Related Posts:

No followup yet

Leave a Response

Comment Preview
« Windows Vista: Debugging a Per-User Installation ErrorBusiness Desktop Deployment renamed to “Microsoft Deployment” »
Feed Icon

Subscribe via RSS or email: