2

関数f()とg()を終了するとどうなりますか?

#include<iostream>
using namespace std;

class A
{
     ~A(){}

}
void f()
{
    cout << "terminate" << endl;

}
void g()
{
    cout << "unexpected" << endl;
}



int main()
{
    set_terminate(f);
    set_unexpected(g);
    throw 5;
    cout << "end" << endl;
    return 0;
}

なぜabort()関数と呼ばれるのですか?そして、いつデストラクタと呼ばれますか?ロジックが見つかりません:(((((((((

4

2 に答える 2

3

誰かがterminate()を呼び出したとき、およびunexpected()を呼び出したときに教えてもらえますか?

この場合、終了ハンドラーが呼び出されます。これはここで確認できます。

に関してstd::terminate()、15.5.1 / 1-2項には、それが呼び出される状況のかなり網羅的なリストを作成する注記が含まれています(太字の部分があなたの場合に当てはまります):

1状況によっては、より巧妙でないエラー処理手法のために、例外処理を破棄する必要があります。[注:これらの状況は次のとおりです。

—例外処理メカニズムが、例外オブジェクトの初期化を完了した後、例外(15.1)のハンドラーをアクティブ化する前に、例外を介して終了する関数を呼び出す場合、または

—例外処理メカニズムが、スローされた例外(15.3)のハンドラーを見つけられない場合、または

—ハンドラーの検索(15.3)が、例外(15.4)を許可しないnoexcept仕様を持つ関数の最も外側のブロックに遭遇した場合、または

—スタックの巻き戻し(15.2)中にオブジェクトの破棄が例外をスローして終了した場合、または

—静的またはスレッドストレージ期間(3.6.2)の非ローカル変数の初期化が例外を介して終了した場合、または

—静的またはスレッドの保存期間を持つオブジェクトの破棄が例外(3.6.3)を介して終了した場合、または

—例外(18.5)に登録された、std::atexitまたは例外を介して終了した関数の実行時、またはstd::at_quick_exit

—オペランドのないthrow-expressionが例外を再スローしようとし、例外が処理されていない場合(15.1)、または

std::unexpected以前に違反したdynamicexception-specificationで許可されていない例外をスローし、std :: bad_exceptionがそのdynamic-exception-specification(15.5.2)に含まれていない場合、または

—実装のデフォルトの予期しない例外ハンドラーが呼び出されたとき(D.11.1)、または

std::nested_exception::rethrow_nested—例外をキャプチャしていないオブジェクト(18.8.6)に対して関数が呼び出された場合、または

—スレッドの初期機能の実行が例外(30.3.1.2)を介して終了した場合、または

—結合可能なスレッド(30.3.1.3、30.3.1.4)を参照するタイプstd::threadのオブジェクトでデストラクタまたはコピー代入演算子が呼び出されたとき。—エンドノート]

2このような場合、std::terminate()は(18.8.3)と呼ばれます。[...]

に関してstd::unexpected()、15.4 / 9項による:

例外がスローされ、ハンドラー(15.3)の検索で、例外を許可しない例外仕様を持つ関数の最も外側のブロックが検出されると、

—例外仕様が動的例外仕様の場合、関数std::unexpected()は(15.5.2)と呼ばれます。

—それ以外の場合、関数std :: terminate()が呼び出されます(15.5.1)。

于 2013-03-16T13:11:46.243 に答える
1

関連するルールは標準で明確に定義されています。いくつかのルールがありますが、簡単に言うと、例に適用されるルールは次のとおりです。

  • throwcatchの呼び出しterminateまたはその関数セット の結果がない場合。
  • スローされた例外が例外仕様と一致しない場合、その例外の呼び出し unexpectedまたは関数セットが発生します。

15.1例外の
スローパラ8:

現在処理されている例外がない場合は、オペランドなしでthrow-expressionを実行すると、terminate()(15.5.1)が呼び出されます。

15.4例外仕様
パラ8:

例外がスローされ、ハンドラー(15.3)の検索で例外仕様のある関数の最も外側のブロックが検出されると、例外仕様で例外が許可されていない場合、関数unexpected()が呼び出されます(15.5.2)。


なぜあなたのプログラムは呼び出すのabortですか?

プログラムの動作は未定義です。terminate_handlerこれは、適切に設定し、プログラムが呼び出しを行うことに気付いたという事実に準拠していますが、関数 f()に必要な動作は次のとおりです。terminate_handler

C ++ 03標準18.6.3.1.2:

terminal_handlerは、呼び出し元に戻らずにプログラムの実行を終了します。

関数がこの条件を満たさないため、未定義の動作が発生します。技術的には、任意の動作を取得できる可能性があります。実装は、この状況で呼び出すことを選択しterminate_handlerます。そうすることを妨げるものは何もありません。fabort

于 2013-03-16T13:11:37.543 に答える