Javaに相当するC ++はありますか
try {
...
}
catch (Throwable t) {
...
}
ネイティブのWindows関数を呼び出すJava / jniコードをデバッグしようとしていますが、仮想マシンがクラッシュし続けます。ネイティブコードは単体テストでは問題なく表示され、jniから呼び出された場合にのみクラッシュするようです。一般的な例外キャッチメカニズムは非常に便利です。
Javaに相当するC ++はありますか
try {
...
}
catch (Throwable t) {
...
}
ネイティブのWindows関数を呼び出すJava / jniコードをデバッグしようとしていますが、仮想マシンがクラッシュし続けます。ネイティブコードは単体テストでは問題なく表示され、jniから呼び出された場合にのみクラッシュするようです。一般的な例外キャッチメカニズムは非常に便利です。
回答:
try{
// ...
} catch (...) {
// ...
}
すべてのC ++例外をキャッチしますが、設計が悪いと考えるべきです。c ++ 11の新しいcurrent_exceptionメカニズムを使用できますが、c ++ 11(書き換えが必要なレガシーコードシステム)を使用する機能がない場合は、メッセージまたは名前を取得するために使用する名前付き例外ポインターがありません。キャッチできるさまざまな例外に対して個別のcatch句を追加し、予期しない例外を記録するために一番下のすべてのものだけをキャッチすることができます。例えば:
try{
// ...
} catch (const std::exception& ex) {
// ...
} catch (const std::string& ex) {
// ...
} catch (...) {
// ...
}
誰かがC ++コードの「クラッシュ」をキャッチできないと付け加えるべきです。それらは例外をスローしませんが、好きなことをします。ヌルポインターの逆参照などが原因でプログラムがクラッシュした場合、そのプログラムは未定義の動作をしています。ありませんstd::null_pointer_exception
。例外をキャッチしようとしても役に立ちません。
誰かがこのスレッドを読んでいて、プログラムクラッシュの原因を取得できると考えている場合にのみです。代わりにgdbのようなデバッガを使用する必要があります。
try { .. } catch(...) { ... }
、シグナル/ シグアクションを使用してキャッチするように実装するまで、「キャッチング」とは呼ばないでしょう:)シグナルハンドラーの場合、プログラマーがコード内のどこでクラッシュが発生したかを知ることは比較的困難です(私は話している)プログラムでそれを検出することについて)、try / catchと比較。
これは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;
}
try {
// ...
} catch (...) {
// ...
}
...
内部catch
は実際の省略記号であることに注意してください。3つのドット。
ただし、C ++の例外は必ずしも基本Exception
クラスのサブクラスではないため、この構成を使用したときにスローされる例外変数を実際に確認する方法はありません。
catch
コメント(// ...
)の中で、指定子を既存のコードプレースホルダーと区別するために言ったのです。
(C ++では)すべての例外を移植可能な方法でキャッチすることはできません。これは、一部の例外がC ++コンテキストの例外ではないためです。これには、エラーゼロによる除算などが含まれます。ハッキングしてこれらのエラーが発生したときに例外をスローする機能を取得することは可能ですが、実行するのは簡単ではありません。
すべてのSTL例外をキャッチしたい場合は、
try { ... } catch( const std::exception &e) { ... }
どちらを使用することもできますe.what()
。これはを返しconst char*
、例外自体について詳しく知ることができます。これは、あなたが尋ねたJava構成に最もよく似た構成です。
誰かがから継承しない例外をスローするほど愚かであれば、これは役に立ちませんstd::exception
。
つまり、を使用します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(...)
です。
Foo
か?それがRAIIの要点だと思いました。ただし、スタックにをFoo
作成するだけでなく、へのポインターが必要な場合Foo
は、スタックで宣言されている別の何かでポインターをラップする必要があります。
これを行うには、次のように記述します。
try
{
//.......
}
catch(...) // <<- catch all
{
//.......
}
しかし、ここでは非常に目立たないリスクがあります。try
ブロックでスローされたエラーの正確なタイプを見つけることができないため、catch
例外のタイプに関係なく、プログラムが持続する必要があることが確実な場合は、この種のエラーを使用してください。catch
ブロックで定義された方法で。
使用できます
catch(...)
しかし、それは非常に危険です。John Robbinsは、彼の著書Debugging Windowsで、catch(...)コマンドによってマスクされた本当に厄介なバグについての戦争の話を語っています。特定の例外をキャッチする方がはるかに優れています。tryブロックが合理的にスローする可能性があると思われるものをすべてキャッチしますが、実際に予期しないことが発生した場合は、コードが例外をスローするようにします。
ここでこれについてお話ししましょう:Java
try
{
...
}
catch (Exception e)
{
...
}
すべての例外をキャッチできるとは限りません!私は実際にこの種のことを以前に起こしたことがあり、それはおかしなことです。例外はThrowableから派生します。文字通り、すべてをキャッチするために、例外をキャッチする必要はありません。Throwableをキャッチしたい。
私はそれが厄介に聞こえることを知っていますが、try ... catch(Exception e)ブロックで囲まれたコードで「キャッチされなかった例外」がどこから来たかを理解しようと数日間費やした場合、それは次のようになります。君は。
catch(Exception)
、Javaですべての例外をキャッチできるわけではありません。C#... Java = catch(Thowable)
、C#= と混同されcatch(Exception)
ます。それらを混乱させないでください。
CoderMalfunctionError
(実際のJava実際にはError
、それはそれはのように聞こえる何を意味するものではありませんが...サブクラス。)
たとえば、すべての例外をキャッチしてミニダンプを作成したい場合は...
誰かが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)にミニダンプが作成されます
一般的な例外キャッチメカニズムは非常に便利です。
疑わしい。コードがクラッシュしているため、コードが壊れていることはすでにわかっています。例外を食べることでこれを隠すことができるかもしれませんが、それは恐らくもっと厄介でより微妙なバグをもたらすだけでしょう。
あなたが本当に欲しいのはデバッガです...
JNIを使用するJavaアプリケーションをコンソールウィンドウから実行(javaコマンドラインから起動)して、JVMがクラッシュする前に検出された可能性のあるレポートがあるかどうかを確認できますか。Javaウィンドウアプリケーションとして直接実行すると、代わりにコンソールウィンドウから実行した場合に表示されるメッセージが表示されない場合があります。
次に、JNI DLL実装をスタブして、DLLのメソッドがJNIから入力されていること、適切に返されていることなどを示すことができますか?
問題がC ++コードのJNIインターフェースメソッドの1つの誤った使用にある場合に備えて、いくつかの簡単なJNI例が設定でコンパイルおよび動作することを確認しましたか?特に、パラメーターをネイティブC ++形式に変換し、関数の結果をJavaタイプに変換するためにJNIインターフェースメソッドを使用することを考えています。それらをスタブ化して、データ変換が機能していて、JNIインターフェースへのCOMのような呼び出しで問題が発生しないことを確認すると便利です。
他にも確認する必要のある事項がありますが、ネイティブJavaメソッドとは何か、それらのJNI実装が何をしようとしているのかについて詳しく知らなければ、提案することは困難です。C ++コードレベルからの例外の捕捉が問題に関連していることは明らかではありません。(JNIインターフェースを使用して、例外をJavaインターフェースとして再スローすることができますが、これが役立つかどうかは、提供された内容からは明らかではありません。)
JNIを使用するプログラムを正しくデバッグできないことに関する実際の問題(または、デバッガーの下でプログラムを実行するときにバグが表示されない):
この場合、いくつかの基本的な健全性チェック(すべての「オブジェクト」が解放され、「オブジェクト」であることを確認する)を行うJNI呼び出し(つまり、すべてのネイティブメソッドはプライベートで、クラスのパブリックメソッドはそれらを呼び出す)の周りにJavaラッパーを追加すると役立ちます。解放後は使用されません)または同期化(1つのDLLからすべてのメソッドを単一のオブジェクトインスタンスに同期化するだけ)。Javaラッパーメソッドに間違いを記録させ、例外をスローさせます。
これは、大規模な並列Javaプログラムをデバッグするよりも簡単に、実際のエラー(驚くべきことに、ほとんどの場合、呼び出された関数のセマンティクスに従わないJavaコードにあり、厄介なdouble-freesなどを引き起こします)を見つけるのに役立ちます。ネイティブデバッガ...
原因がわかっている場合は、それを回避するラッパーメソッドにコードを保持してください。JNIコードがVMをクラッシュさせるよりも、ラッパーメソッドが例外をスローする方が良い...
注意してください
try{
// ...
} catch (...) {
// ...
}
キャッチ唯一の言語レベルの例外のような他の低レベルの例外/エラーAccess Violation
とはSegmentation Fault
キャッチされ文句を言いません。