すべての例外をキャッチするC ++


244

Javaに相当するC ++はありますか

try {
    ...
}
catch (Throwable t) {
    ...
}

ネイティブのWindows関数を呼び出すJava / jniコードをデバッグしようとしていますが、仮想マシンがクラッシュし続けます。ネイティブコードは単体テストでは問題なく表示され、jniから呼び出された場合にのみクラッシュするようです。一般的な例外キャッチメカニズムは非常に便利です。



2
ほとんどのクラッシュはC ++の例外が原因ではないことに注意してください。すべての例外をキャッチできますが、多くのクラッシュを防ぐことはできません。
Mooing Duck 2016

回答:


334
try{
    // ...
} catch (...) {
    // ...
}

すべてのC ++例外をキャッチしますが、設計が悪いと考えるべきです。c ++ 11の新しいcurrent_exceptionメカニズムを使用できますが、c ++ 11(書き換えが必要なレガシーコードシステム)を使用する機能がない場合は、メッセージまたは名前を取得するために使用する名前付き例外ポインターがありません。キャッチできるさまざまな例外に対して個別のcatch句を追加し、予期しない例外を記録するために一番下のすべてのものだけをキャッチすることができます。例えば:

try{
    // ...
} catch (const std::exception& ex) {
    // ...
} catch (const std::string& ex) {
    // ...
} catch (...) {
    // ...
}

68
const参照で例外をキャッチすることをお勧めします。例:catch(std :: exception const&ex){/ * ... * /}
coryan 2008年

12
@coryan:const参照でキャッチするのはなぜ良い習慣なのですか?
Tim MB

19
不要なコピーを回避することは、1つの利点です。
Greg D

21
-1:これが「C ++のすべての例外をキャッチする」という提案は誤解を招くものです。tryブロック内でゼロ除算エラーを生成してみてください。キャッチされない例外が生成されることがわかりますが、コードは明らかにC ++です。これは「すべてのC ++例外をキャッチする」と述べてから、構造化された例外についての言及を、限定された有用性に関する注記に追加するとさらに役立ちます。
omatai 2013

42
@omatai:修正済み、すべてのC ++例外をキャッチします。ゼロによる除算は未定義の動作であり、C ++例外を生成しません。
Mooing Duck 2013

151

誰かがC ++コードの「クラッシュ」をキャッチできないと付け加えるべきです。それらは例外をスローしませんが、好きなことをします。ヌルポインターの逆参照などが原因でプログラムがクラッシュした場合、そのプログラムは未定義の動作をしています。ありませんstd::null_pointer_exception。例外をキャッチしようとしても役に立ちません。

誰かがこのスレッドを読んでいて、プログラムクラッシュの原因を取得できると考えている場合にのみです。代わりにgdbのようなデバッガを使用する必要があります。


4
まあ、シャイが指摘するように、それはVCコンパイラで可能です。それは良い考えではありませんが、可能です。
Shog9 2008年

7
ええSEHと。しかし、まともな標準c ++技術ではありません:)まあ、ウィンドウに固執すれば、ほぼすべてを実行できます:)
ヨハネスシャウブ

1
うーん...この一口に感謝します。私のnullポインター例外がキャッチされない理由についての答えを探してきました!
Dalin Seivewright

10
WindowsのSEHとPOSIXシステムのsignal(2)/ sigaction(2)でsegfaultをキャッチできます。これは、現在使用されているシステムの大多数をカバーしていますが、例外処理と同様に、通常のフロー制御に使用する必要はありません。それは、「死ぬ前に何か役に立つことをする」ということです。
Adam Rosenfield、

1
@AdamRosenfieldはtry { .. } catch(...) { ... }、シグナル/ シグアクションを使用してキャッチするように実装するまで、「キャッチング」とは呼ばないでしょう:)シグナルハンドラーの場合、プログラマーがコード内のどこでクラッシュが発生したかを知ることは比較的困難です(私は話している)プログラムでそれを検出することについて)、try / catchと比較。
Johannes Schaub-litb 14

72

これはcatch(...)、GCCで例外タイプをリバースエンジニアリングする方法です(サードパーティのライブラリから不明をキャッチする場合に役立つことがあります)。

#include <iostream>

#include <exception>
#include <typeinfo>
#include <stdexcept>

int main()
{
    try {
        throw ...; // throw something
    }
    catch(...)
    {
        std::exception_ptr p = std::current_exception();
        std::clog <<(p ? p.__cxa_exception_type()->name() : "null") << std::endl;
    }
    return 1;
}

Boostを使用する余裕がある場合は、キャッチセクションをさらに単純化し(外側で)、潜在的にクロスプラットフォームにすることができます。

catch (...)
{
    std::clog << boost::current_exception_diagnostic_information() << std::endl;
}

58
try {
   // ...
} catch (...) {
   // ...
}

...内部catchは実際の省略記号であることに注意してください。3つのドット。

ただし、C ++の例外は必ずしも基本Exceptionクラスのサブクラスではないため、この構成を使用したときにスローされる例外変数を実際に確認する方法はありません。


24
C ++ 11には次のようなものがあります:try {std :: string()。at(1); //これによりstd :: out_of_range} catch(...){eptr = std :: current_exception();が生成されます //キャプチャー}
Mohammad Alaggan 2013年

2
@bfontaine:ええ、そうですが、C ++構文ではないcatchコメント(// ...)の中で、指定子を既存のコードプレースホルダーと区別するために言ったのです。
グレッグヒューギル2014年

1
@GregHewgill:はい、それは単なる活版印刷のつまらないものでした。
bfontaine 2014年

1
@bfontaine:結構です。:)
グレッグ・ヒューギル2014年

44

(C ++では)すべての例外を移植可能な方法でキャッチすることはできません。これは、一部の例外がC ++コンテキストの例外ではないためです。これには、エラーゼロによる除算などが含まれます。ハッキングしてこれらのエラーが発生したときに例外をスローする機能を取得することは可能ですが、実行するのは簡単ではありません。

すべてのSTL例外をキャッチしたい場合は、

try { ... } catch( const std::exception &e) { ... }

どちらを使用することもできますe.what()。これはを返しconst char*、例外自体について詳しく知ることができます。これは、あなたが尋ねたJava構成に最もよく似た構成です。

誰かがから継承しない例外をスローするほど愚かであれば、これは役に立ちませんstd::exception


2
なぜこれが一番上にないのですか?
Ivan Sanz-Carasa 2018

31

つまり、を使用しますcatch(...)。ただし、これcatch(...)throw;基本的には以下と組み合わせて使用​​するためのものです。

try{
    foo = new Foo;
    bar = new Bar;
}
catch(...)       // will catch all possible errors thrown. 
{ 
    delete foo;
    delete bar;
    throw;       // throw the same error again to be handled somewhere else
}

これはを使用する適切な方法catch(...)です。


6
この例外状況を自動的に処理するメモリ管理にRAIIを使用する方が良いでしょう。
paykoob

1
@paykoob新しいfooを作成するように管理したが、バーで失敗した場合の処理​​方法。または、barのコンストラクターがファイルを開こうとしたが失敗したためスローした場合。それからあなたはdangeling fooで終わるかもしれません
Mellester

2
@MelleSterkその場合、スタックはまだクリーンアップされていませんFooか?それがRAIIの要点だと思いました。ただし、スタックにをFoo作成するだけでなく、へのポインターが必要な場合Fooは、スタックで宣言されている別の何かでポインターをラップする必要があります。
reirab

はいauto foo = std :: make_unique <Foo>(); auto bar = std :: make_unique <Bar>(); //例外安全であり、リークせず、catch(...)も不要
paulm

この回答は、それが始まったディスカッションに限り投票に値します:)
Cristik

21

これを行うには、次のように記述します。

try
{
  //.......
}
catch(...) // <<- catch all
{
  //.......
}

しかし、ここでは非常に目立たないリスクがあります。tryブロックでスローされたエラーの正確なタイプを見つけることができないため、catch例外のタイプに関係なく、プログラムが持続する必要があることが確実な場合は、この種のエラーを使用してください。catchブロックで定義された方法で。


31
優れた回答が提供されてから約5年後に、質問に回答するための何らかのバッジを獲得していただければ幸いです。


18

使用できます

catch(...)

しかし、それは非常に危険です。John Robbinsは、彼の著書Debugging Windowsで、catch(...)コマンドによってマスクされた本当に厄介なバグについての戦争の話を語っています。特定の例外をキャッチする方がはるかに優れています。tryブロックが合理的にスローする可能性があると思われるものをすべてキャッチしますが、実際に予期しないことが発生した場合は、コードが例外をスローするようにします。


1
私はちょうどこれらのいくつかの使用法をキャッチし、その段階でいくつかの伐採にペッパーを付けました。例外を除いて何もしないことは間違いなく問題を求めています。
jxramos 2016年

15

ここでこれについてお話ししましょう:Java

try 
{
...
}
catch (Exception e)
{
...
}

すべての例外をキャッチできるとは限りません!私は実際にこの種のことを以前に起こしたことがあり、それはおかしなことです。例外はThrowableから派生します。文字通り、すべてをキャッチするために、例外をキャッチする必要はありません。Throwableをキャッチしたい。

私はそれが厄介に聞こえることを知っていますが、try ... catch(Exception e)ブロックで囲まれたコードで「キャッチされなかった例外」がどこから来たかを理解しようと数日間費やした場合、それは次のようになります。君は。


2
もちろん、Errorオブジェクトをキャッチするべきではありません-それらをキャッチすることになっている場合、それらは例外になります。エラーオブジェクトは、などのヒープ領域不足など完全に致命的なもの、です
SCDF

1
ほとんどの場合、GoodProgrammerExpected例外であるランタイム例外もありません!!!
OscarRyz 2008年

3
物事を殺すのではなく、catch(Throwable)ブロックが原因でOutOfMemoryErrorをキャッチすることによって引き起こされる本当に深刻なバグがあった...
Trejkaz

1
もちろんcatch(Exception)、Javaですべての例外をキャッチできるわけではありません。C#... Java = catch(Thowable)、C#= と混同されcatch(Exception)ます。それらを混乱させないでください。
ファラオシェフ

2
以下のようなその音@OscarRyz CoderMalfunctionError(実際のJava実際にはError、それはそれはのように聞こえる何を意味するものではありませんが...サブクラス。)
reirab

9

たとえば、すべての例外をキャッチしてミニダンプを作成したい場合は...

誰かがWindowsで作業を行いました。

http://www.codeproject.com/Articles/207464/Exception-Handling-in-Visual-Cplusplusを参照してください。 この記事では、あらゆる種類の例外をキャッチする方法を見つけた方法を説明し、機能するコードを提供しています。

キャッチできるリストは次のとおりです。

 SEH exception
 terminate
 unexpected
 pure virtual method call
 invalid parameter
 new operator fault 
 SIGABR
 SIGFPE
 SIGILL
 SIGINT
 SIGSEGV
 SIGTERM
 Raised exception
C++ typed exception

そして使用法:CCrashHandler ch; ch.SetProcessExceptionHandlers(); //これを1つのスレッドに対して実行しますch.SetThreadExceptionHandlers(); //スレッドごとに


デフォルトでは、現在のディレクトリ(crashdump.dmp)にミニダンプが作成されます


4

一般的な例外キャッチメカニズムは非常に便利です。

疑わしい。コードがクラッシュしているため、コードが壊れていることはすでにわかっています。例外を食べることでこれを隠すことができるかもしれませんが、それは恐らくもっと厄介でより微妙なバグをもたらすだけでしょう。

あなたが本当に欲しいのはデバッガです...


13
私は同意しません。リアルタイムアプリケーションでは、不明な例外をキャッチしたり、ログに何かを書き込んだり、アプリケーションをクラッシュさせるのではなく、一般的なエラーの処理を実行したりするケースがたくさんあります。
f0ster

3
スタックが破棄されたり、メモリが使い果たされたり、一般的なエラー処理が成功しないような状況を無視して、一般的なエラーのコースを追跡できるケースを考えているのではないかと思います。回復可能なエラーをキャッチすることに問題はありませんが、キャッチオールは実際には、プログラムの終了直前に呼び出される慎重に記述されたロジック(分離されたスタック、事前に割り当てられたメモリ)としてのみ存在する必要があります。問題が何であるかがわからない場合は、問題から回復できると確信することができません。
Shog9 '13 / 09/13

1
つまり、ランタイム中にビルドしたログを巻き戻し、プログラムがどこでクラッシュしたか、そしてできればその理由を解明するシグナルハンドラーをインストールします。
2014年

3
  1. JNIを使​​用するJavaアプリケーションをコンソールウィンドウから実行(javaコマンドラインから起動)して、JVMがクラッシュする前に検出された可能性のあるレポートがあるかどうかを確認できますか。Javaウィンドウアプリケーションとして直接実行すると、代わりにコンソールウィンドウから実行した場合に表示されるメッセージが表示されない場合があります。

  2. 次に、JNI DLL実装をスタブして、DLLのメソッドがJNIから入力されていること、適切に返されていることなどを示すことができますか?

  3. 問題がC ++コードのJNIインターフェースメソッドの1つの誤った使用にある場合に備えて、いくつかの簡単なJNI例が設定でコンパイルおよび動作することを確認しましたか?特に、パラメーターをネイティブC ++形式に変換し、関数の結果をJavaタイプに変換するためにJNIインターフェースメソッドを使用することを考えています。それらをスタブ化して、データ変換が機能していて、JNIインターフェースへのCOMのような呼び出しで問題が発生しないことを確認すると便利です。

  4. 他にも確認する必要のある事項がありますが、ネイティブJavaメソッドとは何か、それらのJNI実装が何をしようとしているのかについて詳しく知らなければ、提案することは困難です。C ++コードレベルからの例外の捕捉が問題に関連していることは明らかではありません。(JNIインターフェースを使用して、例外をJavaインターフェースとして再スローすることができますが、これが役立つかどうかは、提供された内容からは明らかではありません。)


2

JNIを使​​用するプログラムを正しくデバッグできないことに関する実際の問題(または、デバッガーの下でプログラムを実行するときにバグが表示されない):

この場合、いくつかの基本的な健全性チェック(すべての「オブジェクト」が解放され、「オブジェクト」であることを確認する)を行うJNI呼び出し(つまり、すべてのネイティブメソッドはプライベートで、クラスのパブリックメソッドはそれらを呼び出す)の周りにJavaラッパーを追加すると役立ちます。解放後は使用されません)または同期化(1つのDLLからすべてのメソッドを単一のオブジェクトインスタンスに同期化するだけ)。Javaラッパーメソッドに間違いを記録させ、例外をスローさせます。

これは、大規模な並列Javaプログラムをデバッグするよりも簡単に、実際のエラー(驚くべきことに、ほとんどの場合、呼び出された関数のセマンティクスに従わないJavaコードにあり、厄介なdouble-freesなどを引き起こします)を見つけるのに役立ちます。ネイティブデバッガ...

原因がわかっている場合は、それを回避するラッパーメソッドにコードを保持してください。JNIコードがVMをクラッシュさせるよりも、ラッパーメソッドが例外をスローする方が良い...


1

まあこれは本当にコンパイラ環境に依存します。gccはこれらをキャッチしません。Visual Studioと、私が使用した最後のBorlandです。

したがって、クラッシュに関する結論は、それが開発環境の品質に依存するということです。

C ++仕様では、catch(...)はすべての例外をキャッチする必要があると述べていますが、すべてのケースでキャッチできるわけではありません。

少なくとも私が試したものから。


1

注意してください

try{
// ...
} catch (...) {
// ...
}

キャッチ唯一の言語レベルの例外のような他の低レベルの例外/エラーAccess ViolationとはSegmentation Faultキャッチされ文句を言いません。


セグメンテーションフォールトのようなものは実際には例外ではなく、信号です。したがって、通常の例外のようにそれらをキャッチすることはできません。ただし、このようないくつかの回避策があります。
MAChitgarha
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.