I recently ran into a problem with a COM object that was using a singleton class factory and had members that were pointers to other COM objects implemented in a different dll than the singleton object. These other COM objects were created by the singleton object and that was the only reference to them. Since the singleton object is never destroyed until its module is unloaded, what seemed to be happening is that sometimes at that point the dll where the other COM objects (members of the singleton) were implemented had already been unloaded and in that case there would be a crash when the singleton released its references to those objects in its destructor. The DLL implementing the other COM objects is aware that there are references held to the objects and returns S_FALSE from its DllCanUnloadNow method. However, this doesn't seem to prevent the DLL from being unloaded always. Is there any safe way to keep member pointers to COM objects from another dll in a singleton COM object?
views:
168answers:
4If you have a pointer (also known as 'hold a reference') to a COM object, then that COM object shouldn't disappear until you release it.
If a COM object hasn't been released, then the DLL in which its code is implemented shouldn't be unloaded: see DllCanUnloadNow.
You may very well be suffering from a "wrong" module unload order. See Why are DLLs unloaded in the "wrong" order? for more information.
When the singleton obtains the implementations of COM interfaces, IUnknown::AddRef should be called on the implementation on the pointers when they are obtained.
The same goes for when you access the fields of the singleton which hold these references. When you get the reference, you should call IUnknown::AddRef, and then when done, call IUnknown::Release.
This way, if the singleton is recycled and all the pointers that it holds are released, if you are holding onto one of them in another section of code, you won't lose the instance, since you incremented the reference count.
You should look into using the CComPtr template as well for helping to manage reference counts:
http://msdn.microsoft.com/en-us/library/ezzw7k98(vs.80).aspx
You might also want to look at the rules for reference counting, which you must adhere to:
http://msdn.microsoft.com/en-us/library/ms810016.aspx
Look for the section titled "Reference-Counting Rules"
Assuming Jeff Stong is right, try one of:
Don't release the COM object (let it leak).
Create a link-time (not just a run-time) dependency from the DLL which contains the singleton to the DLL which contains the COM object.
Tell the singleton to die and/or to release the COM object, before the process starts to die and DLLs begin to be forcibly unloaded.