Background
The application I am working with has several COM DLLs.
One of the COM DLLs has a global singleton object, which stores pointers to COM interfaces in other DLLs. Because it is a global singleton object, I have employed the lazy initialization idiom because it is possible that the interface I am trying to get a pointer to exists in a DLL which hasn't yet been loaded.
(Side-note: This is especially important when registering a single DLL, as the global objects will be constructed within the regsvr32
process, and I don't want the DLL to attempt to acquire an interface to another DLL during this process.)
For example, my lazy initialization method would do something like this:
CComPtr<IMyOtherObject>&
CGlobalSingleton::
GetMyOtherObject()
{
// SNIP: Other code removed for clarity...
if (! m_pMyOtherObject)
{
hr = pUnknown->QueryInterface(IID_IMyOtherObject,
(void**) &m_pMyOtherObject);
}
return m_pMyOtherObject;
}
NOTE: m_pMyOtherObject
is a member variable of the CComPtr
type.
The lazy initialization may not be relevant to my problem here, but I'm including it for completeness.
Problem
What I have noticed is that in some circumstances, I get failed assertions when my application shuts down. However, if I change my code to call QueryInterface()
every time I need to access IID_IMyOtherOBject
(rather than storing it as a member variable) this prevents the assertions.
This appears to me to be a COM object lifetime issue. My hypothesis is that because I am storing
a COM pointer, there needs to be some sort of synchronisation between the destruction of the COM interface that I'm pointing to, and my own pointer to it.
My understanding of the CComPtr
class (which I am using) is that it takes away a lot of the headaches of dealing with lifetime issues (i.e. calling AddRef()
and Release()
). But it doesn't appear to be working in my case.
Can anyone pick what I may be doing wrong?