バックグラウンド
私が使用しているアプリケーションには、いくつかのCOMDLLがあります。
COM DLLの1つには、他のDLLのCOMインターフェイスへのポインタを格納するグローバルシングルトンオブジェクトがあります。これはグローバルシングルトンオブジェクトであるため、ポインタを取得しようとしているインターフェイスがまだロードされていないDLLに存在する可能性があるため、レイジー初期化イディオムを採用しました。
(補足:グローバルオブジェクトはプロセス内で構築されるため、単一のDLLを登録する場合、これは特に重要regsvr32
です。このプロセス中にDLLが別のDLLへのインターフェイスを取得しようとしないようにします。)
たとえば、私の怠惰な初期化メソッドは次のようになります。
CComPtr<IMyOtherObject>&
CGlobalSingleton::
GetMyOtherObject()
{
// SNIP: Other code removed for clarity...
if (! m_pMyOtherObject)
{
hr = pUnknown->QueryInterface(IID_IMyOtherObject,
(void**) &m_pMyOtherObject);
}
return m_pMyOtherObject;
}
注: m_pMyOtherObject
は、このタイプのメンバー変数ですCComPtr
。
怠惰な初期化はここでの私の問題とは関係がないかもしれませんが、完全を期すために含めています。
問題
私が気付いたのは、状況によっては、アプリケーションがシャットダウンしたときにアサーションが失敗することです。ただし、 (メンバー変数として格納するのではなく)アクセスする必要があるQueryInterface()
たびに呼び出すようにコードを変更すると、アサーションが防止されます。IID_IMyOtherOBject
これは、COMオブジェクトの存続期間の問題であるように思われます。私の仮説は、私はstoring
COMポインターであるため、私が指しているCOMインターフェイスの破棄とそれに対する私自身のポインターとの間に何らかの同期が必要であるというものです。
(私が使用している)クラスについての私の理解は、それが生涯の問題(すなわち、電話と)CComPtr
に対処することの多くの頭痛を取り除くということです。しかし、私の場合は機能していないようです。AddRef()
Release()
誰かが私が間違っているかもしれないことを選ぶことができますか?