7

Visual C++ アプリケーションを GCC に移植する作業を行っています (MingW と Linux でビルドする必要があります)。

既存のコードは__try { ... } __except(1) { ... }、いくつかの場所でブロックを使用しているため、最小限のログを実行せずにプログラムを終了させるものはほとんどありません (おそらくメモリ不足タイプのエラーを除いて?)。

GCCで同様のことを行うためのオプションは何ですか?

編集:Visual Studio の /EH オプションへのポインタをありがとう。今必要なのは、Linux でシグナルを処理する方法の例です。2002年からこのメッセージを見つけました。

他にどのようなシグナルSIGFPEがあり、SIGSEVG注意する必要がありますか? (主に、私が何か間違ったことをしているときに発生する可能性のあるものを気にします)

報奨金情報: アプリケーションが終了する前に、できるだけ多くのエラー状態を自己ログできるようにしたいと考えています。

どのようなシグナルを受け取る可能性があり、エラーメッセージをログに記録することが一般的に不可能なシグナルはどれですか? (メモリ不足、他に何?)

Linux と MingW でコードが少なくとも同じように動作する移植可能な方法で、例外と (最も重要な) シグナルを処理するにはどうすればよいでしょうか。#ifdef でOKです。

失敗をログに記録するラッパー プロセスがない理由は、パフォーマンス上の理由から、ディスクへのデータの書き込みを最後の最後まで保存しておくためです。終了します。

4

5 に答える 5

12

try { xxx } catch(...) { xxx } は移植性が高くなりますが、それほどキャッチできない可能性があります。コンパイラの設定と環境に依存します。

デフォルトの VC++ 設定を使用すると、非同期 (SEH) エラーは C++ EH インフラストラクチャに配信されません。それらをキャッチするには、代わりに SEH ハンドラー (__try/__except) を使用する必要があります。VC++ では、C++ エラー処理を介して SEH エラーをルーティングできます。これにより、catch(...) で SEH エラーをトラップできます。これには、ヌル ポインター逆参照などのメモリ エラーが含まれます。 詳細.

ただし、Linux では、Windows が SEH を使用するエラーの多くはシグナルによって示されます。これらは、try/catch によってキャッチされることはありません。それらを処理するには、シグナルハンドラーが必要です。

于 2008-09-02T11:11:01.103 に答える
0

移植性のために、ほとんどのバニラ例外にtry-catchブロックを使用してから、終了ハンドラー(set_terminate_handler)を設定して、壊滅的な終了条件に使用できる最小限のフックを設定します。atexitやon_exitハンドラーのようなものを追加することもできます。もちろん、これらの関数を入力すると、実行環境が奇妙または破損する可能性があるため、正常な環境をどれだけ想定するかに注意してください。

最後に、通常のtry-catchペアを使用する場合、関数の本体でtryブロックを開くのではなく、関数tryブロックの使用を検討できます。

int foo(int x) try {
  // body of foo
} catch (...) {
   // be careful what's done here!
}

それらはC++の比較的未知のチャンクであり、場合によっては、部分的な(小規模な)スタックの破損が発生した場合でも回復を提供する可能性があります。

最後に、はい、おそらく、自分で継続的に処理できるシグナル、または中止する可能性のあるシグナルを調査する必要があります。処理メカニズムを減らしたい場合は、新しい演算子のスローしないバージョンを呼び出すことを検討してください。 、および必要に応じて浮動小数点例外を生成しないようにコンパイルします(自分自身を保護するために、FP結果でisnan(。)、isfinite(。)をいつでも確認できます)。

最後の注意点として、注意してください。浮動小数点の結果分類関数は、LinuxとWindowsでは異なるヘッダーにある可能性があることに気づきました。そのため、これらのインクルードを条件付けする必要がある場合があります。

気分が悪い場合は、setjmpとlongjmpを使用してすべてを記述してください(これは冗談です...)。

于 2008-09-05T22:01:43.650 に答える
0

MSFT 独自の拡張機能の代わりに C++ 標準例外を使用しないのはなぜですか? C++ には例外処理の概念があります。

struct my_exception_type : public logic_error {
    my_exception_type(char const* msg) : logic_error(msg) { }
};

try {
    throw my_exception_type("An error occurred");
} catch (my_exception_type& ex) {
    cerr << ex.what << endl;
}

C++ にも「catchall」句があるため、例外をログに記録する場合は、次のラッパーを使用できます。

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

ただし、これは C++ ではあまり効率的ではありません。これは、このような一般的なラッパーを作成すると、コンパイラによって後続のすべてのスタック フレームに処理コードを挿入する必要があるためです (.NET のようなマネージ システムとは異なり、例外処理は、実際には例外はスローされません)。

于 2008-09-02T11:07:37.913 に答える
0

C++ の例外をcatch(...)既にキャッチすると、トワイライト ゾーンに陥ります。

でキャッチされないエラーをキャッチしようとすると、catch(...)未定義の動作に真っ向から巻き込まれます。動作が保証されている C++ コードはありません。最小限のロギング コードにより、代わりにミサイルが発射される場合があります。

しようとさえしないことをお勧めしcatch(...)ます。有意義かつ安全にログに記録できる例外のみをキャッチし、残りがあれば OS に処理させます。

根本原因の上にエラー処理コードの障害がある場合、事後分析のデバッグは見苦しくなります。

于 2009-07-24T18:34:39.627 に答える
-1

使いやすく、移植可能で、リソースをほとんど使用しない方法の 1 つは、空のクラスをキャッチすることです。最初は奇妙に聞こえるかもしれませんが、非常に便利です。

これは、あなたの質問にも当てはまる別の質問に対して私が作成した例です:リンク

また、複数のキャッチを使用できます。

try
{
   /* code that may throw exceptions */
}
catch (Error1 e1)
{
   /* code if Error1 is thrown */
}
catch (Error2 e2)
{
   /* code if Error2 is thrown */
}
catch (...)
{
   /* any exception that was not expected will be caught here */
}
于 2009-07-23T17:58:00.290 に答える