I have a native C++ ATL in-proc COM server. A separate test program
- calls
CoInitialize()
, - calls
CoCreateInstance()
, then - calls
Release()
on the pointer, - then calls
CoUnitialize()
and exits.
If I run the test program under Visual C++ debugger the debug CRT reports a single memory leak and each time the allocation number is the same.
I used an allocation hook and found out that the object not being returned to the heap is the class factory object.
So basically the following happens:
- the program calls
CoC开发者_开发技巧reateInstance()
- COM internally calls
DllGetClassObject()
- ATL instantiates the factory and passes ownership to the caller (COM internals)
and then the factory is never released - I don't see enough calls to Release()
of the class factory.
What is happening? Is that a defect in COM runtime?
Turns out it's a problem of ATL implementation.
The server uses a global CComModule
class instance. When CComModule::DllClassObject()
is called it creates a class factory instance and caches it in the map referenced by the CComModule
object. So in fact CComModule
object owns the class factory. When CComModule
destructor runs it doesn't release cached class factories.
In order to release all cached class factories CComModule::Term()
method should be called before the server is unloaded. IMO the cleanest way to achieve this is to derive from CComModule
and call CComModule::Term()
in the derived class destructor.
精彩评论