このプログラムでA::~A()
が呼び出されることを期待していましたが、そうではありません。
_#include <iostream>
struct A {
~A() { std::cout << "~A()" << std::endl; }
};
void f() {
A a;
throw "spam";
}
int main() { f(); }
_
ただし、最後の行をに変更すると
_int main() try { f(); } catch (...) { throw; }
_
次に、A::~A()
isが呼び出されます。
Visual Studio 2005の「Microsoft(R)32ビットC/C++最適化コンパイラバージョン14.00.50727.762 for 80x86」でコンパイルしています。コマンドラインは_cl /EHa my.cpp
_です。
コンパイラはいつも通りですか?標準はこの問題について何と言っていますか?
スタックが巻き戻される前に未処理の例外のterminate()が呼び出されるため、デストラクタは呼び出されていません。
C++仕様の具体的な詳細は私の知識の範囲外ですが、gdbとg ++を使用したデバッグトレースはこれを裏付けているようです。
ドラフト標準 セクション15.3の箇条書き9によると:
9一致するハンドラーがプログラムに見つからない場合、関数terminate() (_ except.terminate_)が呼び出されます。 terminal()を呼び出す前にスタックが巻き戻されるかどうか は実装によって定義されます。
C++言語仕様には次のように記載されています。tryブロックからthrow式へのパス上に構築された自動オブジェクトのデストラクタを呼び出すプロセスは「スタックアンワインド」と呼ばれます。元のコードにはtryブロックが含まれていません。スタックの巻き戻しが発生しないのはそのためです。
申し訳ありませんが、標準のコピーを持っていません。
私は間違いなくこれに対する決定的な答えが欲しいので、標準のコピーを持っている誰かが何が起こっているかについて章と詩を共有したいと思います:
私の理解では、終了はiffとのみ呼ばれます。
この質問はグーグルで簡単に検索できるので、ここで私の状況を共有します。
あなたの例外がextern "C"
境界を越えないことを確認するか、MSVCオプション/ EHを使用してください(Extern C関数(/ EH)でC++例外を有効にする=はい)
コンパイラは参照されていないため「a」に関連するコードを生成しないと思いましたが、それでも、デストラクタが実行する必要のあることを行うため、これは正しい動作ではありません。
だから、私はVS2008/vc9(+ SP1)で試してみました、デバッグとリリース、そして例外がスローされた後に〜Aが呼び出され、f()から抜け出します-これは正しい動作です私は正しい。
今、私はVS2005/vc8(+ SP1)で試しましたが、同じ動作です。
確かにブレークポイントを使用しました。コンソールで確認したところ、「〜A」というメッセージも表示されます。多分あなたはどこかでそれを間違えましたか?
2番目の例では、dtorはtry {}ブロックを離れるときに呼び出されます。
最初の例では、main()関数を終了した後にプログラムがシャットダウンするとdtorが呼び出されます。その時点で、coutはすでに破棄されている可能性があります。