27

デストラクタで例外をキャッチしてから再スローすることは可能ですか? もしそうなら、声明
のための明確な場所がないので、どうすればいいですか?try

基本的に、私は理想的にやりたい:

CMyObject::~CMyObject()  
{
    catch(...)    // Catch without a try.  Possible?
    {
        LogSomeInfo();
        throw;  // re-throw the same exception
    }
    // Normal Destructor operations
}

背景
どこかで未処理の例外をスローしている大規模で複雑なアプリケーションがあります。トップレベルのメッセージポンプなどに簡単にアクセスできないmainため、未処理の例外をすべてキャッチする簡単な場所がありません。

ハンドルされていない例外は、スタックが巻き戻されるときに一連のデストラクタを通過する必要があると思います。だから、私はcatchデストラクタでたくさんのステートメントを分散させることを考えています。そうすれば、少なくとも、例外がスローされたときにどのオブジェクトが動作しているかがわかります。しかし、これが可能かどうか、または推奨されるかどうかはわかりません。

4

3 に答える 3

17

EDIT :std::uncaught_exception例外が現在スローされているかどうかを確認するために使用できます (つまり、例外のためにスタックの巻き戻しが進行中かどうか)。その例外をキャッチしたり、デストラクタからアクセスしたりすることはできません。したがって、ログが例外自体にアクセスする必要がない場合は、使用できます

CMyObject::~CMyObject()  
{
  if(std::uncaught_exception()) {
    LogSomeInfo(); // No access to exception.
  }
  // Normal Destructor operations
}

この質問は 2013 年に行われましたが、一方、 (最後に追加があることに注意してください) を返すものstd::uncaught_exceptionに置き換えられたことに注意してください。根拠については、http: //www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4152.pdf を参照してください。したがって、C++17 を使用している場合は、新しいバージョンを優先する必要があります。上記の論文では、古いバージョンが一部の状況で期待どおりに機能しない理由についても説明しています。std::uncaught_exceptionssintstd::uncaught_exception


別のオプションかもしれませんstd::set_terminate。これは、例外がキャッチされず、プログラムを終了しようとしているときにメソッドを呼び出したい場合に便利です。終了ハンドラーでは、通常、例外に関する情報と、例外が発生した場所の (デマングルされた) バックトレースをログ ファイルに出力してから、プログラムを最終的に終了します。これはコンパイラとシステム固有のものですが、サーバー プロセスを記述し、多くの場合、ops から取得するのはログ ファイルだけである場合、多くの時間を節約できるため、真のヘルパーです。

于 2013-09-23T15:54:15.130 に答える
8

std::uncaught_exception()処理中の例外がある場合にのみ true を返す whichを使用できます。これは C++98 以降で使用可能であり、これに取って代わられましstd::current_exceptionstd::exception_ptr

ただし、保護されていないコンテキストで別の例外をスローしないように注意する必要があります。そうしないstd::terminateと、キャッチされます。例:

X::~X() {
    if (std::uncaught_exception()) {
        try {
            LogSomeInfo();
            // and do something else...
        } catch(...) {}
    }
}
于 2013-09-23T18:35:15.527 に答える