web-dev-qa-db-ja.com

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

Javaと同等のC++はありますか

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

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

212
Obediah Stane
try{
    // ...
} catch (...) {
    // ...
}

すべてのC++例外をキャッチしますが、それは悪い設計と見なされるべきです。 c ++ 11の新しいcurrent_exceptionメカニズムを使用できますが、c ++ 11(書き換えが必要な従来のコードシステム)を使用できない場合は、メッセージまたは名前を取得するために使用する名前付き例外ポインタはありません。 。あなたはあなたが捕らえることができる様々な例外のために別々のcatch節を追加することを望むかもしれず、そして予期しない例外を記録するために一番下のすべてを捕らえるだけです。例えば。:

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

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

念のために、誰かがこのスレッドを読んでいて、彼がプログラムクラッシュの原因を得ることができると思います。代わりにgdbのようなデバッガを使うべきです。

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

catch内の...は本当の省略記号です。 3つの点.

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

56
Greg Hewgill

GCCでcatch(...)の中から例外の型をリバースエンジニアリングすることができます(サードパーティのライブラリから未知のものを捕らえるときに役に立つかもしれません):

#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セクションをさらに単純に(外側で)そして潜在的にクロスプラットフォームにすることができます

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

移植性のある方法ですべての例外を捕捉することは不可能です(C++)。これは、一部の例外がC++コンテキストでは例外ではないためです。これには、ゼロエラーによる除算などのものが含まれます。このようなエラーが発生したときにハッキングして例外をスローする可能性があります。

あなたがすべてのSTL例外をキャッチしたい場合は、することができます

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

これはe.what()を使うことを可能にします、そしてそれはconst char*を返すでしょう。これは、Javaコンストラクトによく似たコンストラクトです。

誰かがstd::exceptionから継承しない例外を投げるほど愚かであるならば、これはあなたを助けません。

34
Clearer

要するに、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(...)の正しい使い方です。

21
Mellester

書くことによってこれをすることは可能である:

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

しかし、ここではあまり目立たないリスクがあります。tryブロックでスローされた正確なエラーの種類を見つけることができないので、例外の種類が何であれ、この種のcatchを使用してください。 catchブロックで定義された方法で存続する必要があります。

18
Infintyyy

あなたが使用することができます

catch(...)

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

17
John D. Cook

ここで言及しておきます。Java

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

すべての例外をキャッチすることはできません。私は実際にこのようなことを以前にも経験したことがありますが、それは気まずい思いをさせます。例外はThrowableから派生します。文字通り、すべてを捉えるためには、例外を捉えたくはありません。あなたはThrowableをキャッチしたいです。

私はそれが厄介に聞こえますが、try ... catch(Exception e) "ブロックに囲まれたコードのどこで"キャッチされていない例外 "が発生したのかを突き止めようと数日間費やした場合、君は。

12
Paul Sonier

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

誰かが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)にミニダンプを作成します。

7
Aftershock

一般的な例外捕捉メカニズムは非常に便利です。

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

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

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

  2. 次に、DLL内のメソッドがJNIから入力されていること、正しく戻っていることなどを示すために、JNI DLL実装をスタブすることができますか。

  3. 念のために、C++コードのJNIインターフェース・メソッドの1つを誤って使用したことが原因で、いくつかの簡単なJNIの例があなたのセットアップでコンパイルされ動作することを確認しましたか?特に、パラメータをネイティブのC++形式に変換したり、関数の結果をJava型に変換したりするためにJNIインターフェース・メソッドを使用することを考えています。データ変換が機能していること、そしてJNIインターフェイスへのCOMのような呼び出しに煩わされていないことを確認するためにそれらをスタブ化することは有用です。

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

2
orcmid

JNIを使​​用するプログラムを正しくデバッグできないという本当の問題(またはデバッガで実行してもバグが表示されない):

この場合、いくつかの基本的な健全性チェック(すべての「オブジェクト」が解放され、「オブジェクト」がチェックされていることを確認)を行うJavaラッパーをJNI呼び出しに追加します解放した後や同期化(1つのDLLから単一のオブジェクトインスタンスへのすべてのメソッドの同期) Javaラッパー・メソッドに間違いを記録させ、例外をスローさせます。

これは実際のエラー(驚くほど驚くべきことに、呼び出された関数のセマンティクスに従っていくつかの厄介な二重解放などを起こさないJavaコードにある)を見つけるのに役立ちます。ネイティブデバッガ...

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

1
mihi

まあこれは本当にコンパイラ環境に依存します。 gccはこれらを捕まえません。 Visual Studioと私が使った最後のBorlandがやった。

そのため、クラッシュに関する結論は、開発環境の質に左右されるということです。

C++仕様では、catch(...)はすべての例外をキャッチする必要があるとしていますが、それはすべての場合ではありません。

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

0
Jan