11

私はそのようなプロジェクトでいくつかのコードを見つけました:

int main(int argc, char *argv[])
{
  // some stuff

 try {
  theApp.Run();
 } catch (std::exception& exc) {
  cerr << exc.what() << std::endl;
  exit(EXIT_FAILURE);
 }
 return (EXIT_SUCCESS);
}

例外がキャッチされる理由がわかりません。そうでない場合、アプリケーションは単純に終了し、例外が出力されます。

ここで例外をキャッチする正当な理由はありますか?


編集:例外エラーを出力するのが良いことに同意します。ただし、例外を再スローした方がよいのではないでしょうか? ここで飲み込んでいるような気がします...

4

7 に答える 7

16

例外がキャッチされない場合、標準はスタックが巻き戻されるかどうかを定義しません。そのため、一部のプラットフォームではデストラクタが呼び出され、その他のプラットフォームではプログラムがすぐに終了します。トップレベルでキャッチすると、デストラクタが常に呼び出されます。

したがって、デバッガーで実行していない場合は、std::exceptionだけでなくすべてをキャッチするのが賢明です。そうすれば、致命的な例外が発生した場合でも、アプリケーションコードをRAIIでクリーンアップできます。多くの場合、OSが自動的にクリーンアップするため、実際にクリーンアップする必要はありません。ただし、たとえば、可能な場合はリモートサービスから完全に切断したい場合や、名前付きパイプやミューテックスなど、リークではなく破棄したいリソースがプロセスの外部にある場合があります。

mainで例外を再スローすることは、最初にスローされたコンテキストをすでに失っているため、使用が制限されているように見えます。デバッガーでキャッチされなかった例外をトラップすることは、単に障害をstd :: cerrにログに記録するよりもノイズが多いと思います。したがって、ログを見逃す可能性がある場合は、再スローするのが賢明です。

デバッガーがデバッグモードで予期しない条件をトラップするようにしたい場合、リリースモードでは例外がスローされ、最終的には終了します。例外をキャッチせずに残してデバッガーに認識させる以外の方法があります。たとえば、assertマクロを使用できます。もちろん、これは、.NETでSEHを使用している場合のハードウェア例外など、予期しない予測できない状況には役立ちません。

于 2008-12-15T12:57:27.060 に答える
6

なぜ例外が出力されると言うのですか? これは、C++ ランタイムの典型的な動作ではありません。せいぜい、そのタイプが出力されることを期待できます。

さらに、このプログラムは「失敗」ステータスのままになりますが、例外が発生すると、中断による終了ステータスが発生する可能性があります (つまり、終了コードにシグナルが示されます)。

于 2008-12-15T12:17:43.397 に答える
6

メイン関数の try-catch は、デバッガーから例外を隠します。私は、それは良くないと言うでしょう。

一方、顧客がデバッガーを持っていることは想定されていないため、例外をキャッチすることは良いことです。それでいいです。

個人的には、リリース ビルドを作成するときはメイン関数ですべての例外をキャッチしますが、デバッグ構成をビルドするときはそうしません。

于 2008-12-15T12:22:48.923 に答える
5

スタックが巻き戻されなかった状況の簡単な例:
例外でデストラクタが呼び出されないのはなぜですか?

スタックをアンワインドするのではなく、例外によってアプリケーションが終了する可能性がある状況のリスト。
例外でデストラクタが呼び出されないのはなぜですか?

例外がどのレベルでもキャッチされず、main() をエスケープする場合、実装は、スタックをアンワインドするのではなく、terminate() を呼び出すことが許可されます (はい、これにも驚きました)。

その結果、私は常にすべての例外を main() でキャッチします。

int main()
{
    try
    {
    }
    catch(std::exception const& e)
    {  /* LOG */
       // optimally rethrow
    }
    catch(...) // Catch anything else.
    {  /* LOG */
       // optimally rethrow
    }
}

デバッグ中に問題をキャッチするのに役立ちます。std::exception から例外を派生させ、std::exception のコンストラクターにブレーク ポイントを貼り付けます。

于 2008-12-15T15:42:15.823 に答える
3

これはグローバル catch ブロックです。不可解な例外の出力ではなく、適切でユーザーが理解できるメッセージ (「内部エラー」) を表示するのが一般的です。これは、特定のコード ブロックからは明らかではないかもしれませんが、一般的には良い考えです。

于 2008-12-15T12:20:19.570 に答える
0

C ++聖書、すなわちStroustrupを見てください。彼には、AppliedC++プログラミングでも繰り返されている例があります。理由は次のとおりです。

int main(void)
{
     try
     {
          // your code 
     }
     catch ( /* YourPossibleExceptions i.e. barfs you expect may occur */ )
     {
     }
     catch ( ... ) // unexpected errors, so you can exit gracefully
     {
     }
}
于 2008-12-15T12:29:06.400 に答える
0

Windows の仕様によると、mainをスローすることは許可されていません。(実際には、バグレポートをマイクロソフトに送信するかどうかを尋ねるメッセージが表示されます)

于 2012-08-06T09:35:36.830 に答える