2009-07-29 14 views
1

私たちはコード内でネイティブCOMサポートを使用しています。 __com_raise_error()が呼び出され、_com_error例外がスローされるという事実が気に入らないという点を除いて、すべてうまくいっています。この_com_errorを捕捉する独自の階層構造を持っているので、これは階層構造ではなく、std :: exceptionから継承しないことさえありません。IErrorInfoの所有者は誰ですか?

したがって、_com_raise_error()をオーバーライドする必要があります。それは単体で簡単です。コード内で定義するだけで、リンカーはそれをリンクします。

ただし、IErrorInfoの所有者は不明です。署名は

void __stdcall _com_raise_error(HRESULT hr, IErrorInfo* info); 

です。関数を呼び出す人は誰でも関数が返ってからIErrorInfo :: Release()を呼び出す責任があります。しかし、私たちが例外をスローしてコントロールがどこか他のものに移動すると、関数はどのように戻りますか?

この関数に入るとすぐにAddRef()、次にRelease()が呼び出されました。参照カウンタは1になりました。その後、構築された例外オブジェクトに所有権を渡します。そのコンストラクタではAddRef )デストラクタで。 AddRef()は参照カウントを2に増やしますが、(例外デストラクタでは)1つのRelease()しか呼び出されないので、これは間違っていると思います。

コンストラクタ内のAddRef()がメモリリークを引き起こすか、IErrorInfoオブジェクトがまったくリークできない内部メカニズムがあることを修正しましたか?

答えて

1

私は_com_raise_errorがオブジェクトを渡してSetErrorInfoと呼ぶと思います。その契約は、情報への参照がローカルのスレッドに保存されるため、新しい情報を設定するたびに古い情報が解放されるということです。さらに、その後誰かがGetErrorInfoに電話すると、その情報の所有権がその発信者に転送されます。だから、それを設定する可能性があるすべての失敗したコールの後にGetErrorInfoに電話をかけ、それに応じてオブジェクトを解放するのは発信者の義務です。あなたが返すように意図されていない1

2

_com_raise_error()のカウンターでそれを初期化してはいけませんんので、

したがって、(任意の他の従来のCOM呼び出しなど)SetErrorInfoは、あなたのオブジェクトにAddRefを呼び出します。型に関係なく、例外を発生させる必要があります。 _com_raise_error()の既定の実装を見ると、呼び出された_com_errorオブジェクトは、指定されたIErrorInfoオブジェクトの所有権を取得します。 _com_errorのコンストラクターにfAddRefパラメーターがあり、既定値falseの場合、AddRef()は呼び出されません。 _com_errorオブジェクトがそれをキャッチする例外ハンドラによって破棄されると、Release()が呼び出され、IErrorInfoオブジェクトが解放されます。ここでは、他の回答に追加

1

は思考のカップルです:

  • 一般的なCOMルールがインパラメータにAddRefする必要はないということです。どのレベルのED、呼び出しが同期しているのでメソッドが実行されている間に参照カウントが魔法のように変更されることはありません。

  • すべてのAddRef呼び出しは、オブジェクトへの新しい安定した参照を表します。つまり、AddRefを呼び出した後でも、そこにまだ存在するオブジェクトをカウントできます。つまり、後で熟読できるようにインターフェイスポインタを格納したい場合は、AddRefを呼び出す必要があります。オブジェクトの生存を気にしなくなったら、Releaseを呼び出します。あなたがIErrorInfoポインタを含む例外オブジェクトをスローするようにしたいので、それが生き残るための尖ったツーオブジェクトを必要とするため

ので、そのオブジェクトは、それに対してAddRefを実行する必要があります。そのデストラクタは通常リリースします。

私はSetErrorInfoがこれに関与する必要があるとは思わない - それは例外を投げる代わりのCです。

関連する問題