今日、自分のコードで、自分の COM オブジェクトを IUnknown** にキャストすることによって、AFAICT というアクセス違反が発生するという問題に遭遇しました。渡された関数は問題なく実行されましたが、オブジェクトの関数の1つを呼び出すと、ランダムな関数が実行され、スタックが破損してから死にました。
示唆的なコード (なぜこのように行われたのかは無視してください - 私はそれが悪いことを知っており、それを修正する方法を知っていますが、これはなぜこのような問題が発生するのかという問題です):
void MyClass2::func(IMyInterface* pMyObj)
{
CComPtr<IMyInterface2> pMyObj2;
HRESULT hRes = pMyObj->GetInternalObject((IUnknown**)&pMyObj2);
if (SUCCEEDED(hRes))
pMyObj2->Function(); // corrupt stack
}
void MyClass::GetInternalObject(IUnknown** lpUnknown)
{
pInternalObject->QueryInterface(IID_IMyInterface2, (void**)lpUnknown);
}
私は常に、COM オブジェクトで C/C++ キャストを使用することに少し疑いを持っていましたが、これまで (おそらく未定義の動作による) 問題に遭遇したことはありません。
簡単に調べてみたところ、継承チェーンに複数の相互関係がない限り、IUnknown へのキャストは技術的に有効であることがわかりますが、ベスト プラクティスとは見なされません。実際に IUnknown を渡してからMyClass::GetInternalObject(IUnknown** lpUnknown)
、戻り値をクエリする必要があります。必要なインターフェイスの値。
私の質問は、COM オブジェクトで C/C++ キャストをいつ使用できるかについての規則はありますか? また、多重継承とそれらがもたらすアジャスター サンクは別として、COM オブジェクトのキャストがアクセス違反のような予期せぬ結果をもたらすのはどうしてでしょうか? 詳しく教えてください。
編集:これらはすべて、適切に実行する方法の良い例ですが、私が望んでいたのは、COMオブジェクトをキャストしてはならない理由の技術的な説明でした(存在する場合)。たとえば、キャストすると状況xでpMyObj2-4が返されますが、 QueryInterface はyのために pMyObj2-8 を返します ...または COM オブジェクトのキャストは単に悪い習慣/スタイルの問題ですか?
ティア