私はちょうどthis questionに尋ねました。要するに、win32タイマーのコールバックからスローすると、その例外はどこにも出てこないように見えます。それはWindowsのどこかで秘密裏に扱われているようだ。win32タイマーコールバックを投げたときにデストラクタが呼び出されないのはなぜですか?
OKよく問題です。問題のもう一つの側面は、この例外がスローされたときにデストラクタが呼び出されていないように見えるということです。次のコードでは、CFooのの場合、GetFooVectの一時変数が破棄され、rValueがfooVectにコピーされたときに、 "〜CFoo"という唯一の時間が出力されます。 fooVectの内容は破壊されません。
これは私の最悪の悪夢です。私はかなりRAIIを使用します。私はデストラクタにかなり頼りにして、適切にクリーンアップします。
class CFoo
{
public:
~CFoo() {printf(__FUNCTION__ "\n");}
};
std::vector<CFoo> GetFooVect()
{
std::vector<CFoo> rValue;
rValue.push_back(CFoo());
rValue.push_back(CFoo());
rValue.push_back(CFoo());
return rValue;
}
VOID CALLBACK Timer(HWND hwnd,
UINT uMsg,
UINT_PTR idEvent,
DWORD dwTime)
{
// My destructors aren't called?
std::vector< CFoo> fooVect = GetFooVect();
// I'm destroyed
CFoo aFoo;
throw FooExcept();
printf("Also Here\n");
}
私は単純にC++の例外(つまり、Win32のタイマーコールバック変数を削除)し、CFooの破棄のベクトルだけで罰金をキャッチ/スローすることによって、これを再作成しようとしました。なんらかの理由で、デストラクタはベクトルのもののためにここで呼び出されていません。何がありますか?これについて論理的な説明がありますか、それともちょっと変わったのでしょうか、あるいはその両方ですか?
+1:決してWin32コールバックまたはCOMインターフェイスメソッドから例外をスローしません。そうすることは本質的に未定義の動作です。これらのいずれかで例外を使用している場合は、戻る前に* everything *をキャッチしてから、通常の戻りコードを返します。例外を上位に伝播させたい場合は、他の場所に状態を保存し、APIを使用して正常に戻り、エラーをチェックして、コントロールが自分のコードに戻ったときに再びスローします。 – BrendanMcK
ここで起こっている可能性がありますC++ランタイムは、例外の実装において低レベルの構造化例外処理(SEH)機能を使用しており、Win32のコードもSEHを使用していますが、独自の目的でC++ランタイムを妨害します。これは、C++の実行時に例外を実装するC++ランタイムがコンパイルするコードまたはコンパイラに同梱されているライブラリに対して「管轄」しか持たないためです。 Win32コードモジュールとDLLは独自の宇宙です。同様に、Win32やCOMから返される任意のオブジェクトではなく、独自のコードのオブジェクトに対してのみC++ RTTIを使用できます。 – BrendanMcK
デストラクタは、ランタイムがC++ catchブロックを見つけるまで実行されません。もちろん、Timerコールバックの上にあるコールスタックではそれほど高くありません。 –