2

私は現在、クローズド ソースの VB アプリケーションで使用される COM サーバー (ATL を使用) に取り組んでいます。これまでのところすべてが機能していますが、漏れがないことを確認したいので、私の質問は次のとおりです。

次の方法で取得した IDispatch ポインターで AddRef や Release を呼び出す必要がありますか?

VARIANT pVar;
IDispatch->Invoke(dwDispID, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET,
                  &dispparamsNoArgs, &pVar, NULL, NULL);
4

2 に答える 2

4

pVarインターフェイス ポインタ (IUnknown*または) を保持している場合は、既に供給さIDispatch*れたものを受け取ります。AddRef完了したら、一致するリリースを行う責任があります。これは通常、バリアントを間接的にクリーンアップするだけですVariantClear

この関数は、vt フィールドを VT_EMPTY に設定することにより、VARIANTARG をクリアします。VARIANTARG の現在のコンテンツが最初にリリースされます。[...] vtfield が VT_DISPATCH の場合、オブジェクトは解放されます。[...]

ちなみに、ATL でプロパティを読み取るために Invoke を使用する必要はありません。すぐに利用できる便利なヘルパーがあります。

CComPtr<IDispatch> pDispatch;
CComVariant vFoo;
HRESULT nFooResult = pDispatch.GetPropertyByName(L"Foo", &vFoo);
CComVariant vBar;
HRESULT nBarResult = pDispatch.GetProperty(DISPID_BAR, &vBar);

ラッパー クラスが参照管理を処理します。

于 2013-06-13T14:53:24.653 に答える
1

AddRef() は、IDispatch ポインターで既に呼び出されています。ほとんどの場合、サーバーの QueryInterface() メソッドなど、目に見えないコードで発生します。ATLでかなりうまく隠されています。そのため、呼び出し中にインターフェイス ポインターが無効になることはなく、参照カウントは少なくとも 1 になります。作業が終わったら必ず Release() を呼び出してください。

Fwiw、通常はこれを ATL の CComPtr または CComQIPtr スマート ポインター クラスに任せます。それらは AddRef/Release 呼び出しを自動的に生成します。

メモリ リークを追跡している場合は、欠落している Release() 呼び出しを探します。

于 2013-06-13T16:02:53.580 に答える