1

IDispatch/IUnknownポインターから見える__vfptrと混同しました。インプロセスフリースレッドCOMobj(IMyContainer)を作成しています。このオブジェクト内には、同じIMyInterfaceを実装するcomオブジェクトの2つの異なるインスタンスへのポインターを保持する必要があります。そこで、CreateAndSaveDispToMap()を2回呼び出します。

私の考えは、IDispatchポインタをいくつかのstd::mapに保持することです。現時点では、各インスタンスのrefCountは1であると思われます。しかし、驚いたことに、2つの異なるディスパッチポインタに対してpUnkを介して同じ__vftblを取得していることがわかります。

なんで?AddRef()とRelease()が正常に機能する可能性はどのようにありますか?

HRESULT CMyContainer::CreateAndSaveDispToMap(...)
{
...
IMyInterface* pMyInterface = NULL;
hr = ::CoCreateInstance(CLSID_MyInterface, NULL, CLSCTX_INPROC_SERVER, IID_IMyInterface, (void**)&pMyInterface);
pMyInterface->QueryInterface(IID_IDispatch, (void**)&pDisp);
pMyInterface->Release();    // Call Release since QI already called AddRef()
...

IUnknown* pUnk = NULL;
pDisp->QueryInterface(IID_IUnknown, (void**)&pUnk);
int refCount = pUnk->Release();
...
AddToMap(pDisp);
}
4

2 に答える 2

0

各ポリモーフィックオブジェクトには__vfptr、オブジェクトの実際のクラスのvtableへのポインタであるがあります。個別のクラスごとに1つのvtableが生成されます。そのため、同じクラスの2つのオブジェクトの場合、それら__vfptrのオブジェクトの値は同じになります。

異なるCOMオブジェクトを区別するために、それらのIUnknownインターフェイスポインタを取得して比較します。これはオブジェクトIDと呼ばれます。

于 2011-11-11T06:41:31.980 に答える
0

おかげで、IUnknownの関数のアドレスは同じであり、そうである必要があることがわかりました。

ただし、AddRef/Releaseの動作を過小評価しないでください。ExposePointer()でデバッグモードに入ると、2回目の連続呼び出しではrefCountが3に戻らないことがわかります。これにより、2に戻ります。

しかし、代わりにForgetExposePointer()を2回呼び出すと、3になります。

Variant * Resultを介してディスパッチポインタを返す、またはそのような値を返すのを忘れると、異なる結果が得られるのはなぜですか?呼び出し1と呼び出し2の間に、Release()への隠された呼び出しが発生することを理解しています...

STDMETHODIMP CMyContainer::ExposePointer([in]int index, [out, retval] VARIANT* Result)
{
VariantInit(Result);
IDispatch* pDisp = m_map[index].second;
V_VT(Result) = VT_DISPATCH;
V_DISPATCH(Result) = pDisp;
refCount_x = pDisp->AddRef();    // Increment, because we expose
}

STDMETHODIMP CMyContainer::ForgetExposePointer([in]int index, [out, retval] VARIANT* Result)
{
VariantInit(Result);
IDispatch* pDisp = m_map[index].second;
refCount_y = pDisp->AddRef();
}


MyApp::Function1(...)
{
CreateAndSaveDispToMap(...);   // refCount is 1 now
VARIANT var1;
VARIANT var2;
pMyContainer->ExposePointer(index, &var1);  // Call 1
pMyContainer->ExposePointer(index, &var2);  // Call 2
}
MyApp::Function2(...)
{
CreateAndSaveDispToMap(...);   // refCount is 1 now
VARIANT var1;
VARIANT var2;
pMyContainer->ForgetExposePointer(index, &var1);
pMyContainer->ForgetExposePointer(index, &var2);
}
于 2011-11-11T17:02:10.260 に答える