2

構造化例外処理は悪いですか? 例外を処理する正しい方法は何ですか?

編集: C# を使用した .NET での例外処理。

通常、特定の例外クラス (DivideByZeroException、ArrayTypeMismatchException) のセットがあり、一般的な "catch (Exception ex)" はありません。

この背後にある考え方は、特定の種類の例外が発生し、それらが発生したときに特定のアクションが定義され、予期しない例外がインターフェイス (ウィンドウまたは Web) に表示されることを期待しているということです。これは良い習慣ですか?

4

5 に答える 5

6

「構造化された例外処理」の意味がわかりません。

例外処理で実行できる最悪のことは、例外を「飲み込む」か、サイレントに処理することです。

こんなことしないで:

try {
   ...
}
catch (Exception e) {
   //TODO: handle this later
}

これは、コードをコンパイルするための怠惰から行われることがよくあります。特定のレベルで例外を処理する方法がわからない場合は、メソッドに例外をスローさせ、少なくとも最上位にすべてのハンドラーをキャッチさせます。問題が最終的に修正されるように、何らかの方法でフィードバックを提供します(GUI、サポート担当者へのページ/電子メール、ログファイルを介して)。例外をサイレントにキャッチすると、ほとんどの場合、後で大きな問題が発生し、追跡が困難になります。

于 2008-12-09T14:39:49.163 に答える
3

catch ステートメント + スタック トレース。スタック トレースを出力せずに例外をキャッチしないでください。エラーが発生し、ログ ファイルが空またはあいまいな場合、あなたまたは他の誰かがそのコードを再度チェックアウトし、Catch ブロックにスタック トレースを配置する必要があります。

于 2008-12-09T14:33:19.707 に答える
1

これは複雑なトピックです...これに関する本があります...しかし...例外処理には2つの主要なタイプがあります...インライン、潜在的なエラーを処理するコードは、メソッドまたはルーチンのコードとインラインですコードが他の場所にある場合、「通常」実行され、構造化された例外処理が実行されます。インフラストラクチャは、予期しないイベント(エラー)が発生したときにその例外処理コードに自動的に切り替えられるように設計されています...どちらにも長所と短所があります。「インライン」アプローチは、(エラーコードを含む)はるかに雑然としたコードを生成する傾向があり、読み取りと保守が困難です。ただし、事前の分析を必要としないため、事前に作成する方が簡単です。インラインエラー処理を使用する場合、ブール値または数値の「エラー」コードを返すメソッドがよく見られます。metjhodまたはルーチンが成功したかどうかを発信者に示します。これにより、ルーチンが意味のあるビジネス値またはオブジェクトを「返す」という「機能的な」構文が排除されます(慣例により、すべての関数はエラーコードを返す必要があるため)。構造化例外処理を使用する場合、この問題は重要ではありません。

構造化例外処理、otohは、ルーチンまたはメソッドが生成する可能性のあるエラー、およびエラーが発生した場合にメソッドが各エラーに対して実行できる、または実行する必要があるエラーについて事前に分析する必要があるため、一般にうまく実行するのが困難です。

確かなことの1つは、2つのアプローチを1つのコンポーネントに混在させないことです。

于 2008-12-09T14:59:05.803 に答える
1

私の推薦:

次の場合を除いて、例外をキャッチしないでください。

  • そうしないと、アプリケーションがクラッシュします(イベントハンドラーなど)
    • そして、この状況では、何がいつ起こったかを知るために、必ず例外をログに記録してください。
  • 状況を改善するために何かを行うことができます(たとえば、例外をスローする外部APIを呼び出すときに再試行メカニズムを実装する(プログラムフローを制御するために例外処理を使用しないように注意してください))
    • そしてこの状況では、スローされると予想される特定の例外タイプのみをキャッチします

可能な限り最高のレベルで例外をキャッチすることは、最大の呼び出しスタックを取得することを意味します。これは、ログを調べて、最初に例外を引き起こした一連のイベントをトリガーした最初のアクションを確認するときに非常に役立ちます。 。

于 2008-12-09T14:45:21.960 に答える
0

私は Windows プログラマーではありませんが、構造化された例外処理を使用してハードウェア例外をソフトウェア例外のように扱うことは、次のことを意味しているように思えます。

  • あなたのコードは、C++ 標準で未定義または実装定義の動作 (ゼロ除算など) を生成することを行います。
  • Windows では、SEH を有効にすると、その場合に例外がスローされると定義されています。
  • この事実を使用して、例外をキャッチしたり、終了ハンドラーを実行したりします。

したがって、IMOに尋ねる質問は次のとおりです。

  • あなたのプログラミング タスクは、標準の C++ では処理できない性質のものですか? (または、ハードウェア例外を許可することによって得られるものよりもかなり劣る方法でのみ処理できます)。
  • コードが非標準になったときに、本当に対策を講じる必要がありますか?
  • そもそもハードウェア例外を引き起こさないようにコードを書くことができますか?

答えが「はい」、「はい」、「いいえ」の場合、構造化例外処理が必要です。それ以外の場合は、回避できる可能性があります。その場合は、回避したいでしょう。例外セーフなコードを書くのは難しいので、提供できる例外保証が強力であればあるほど、より良い結果が得られます。SEH でゼロ除算する可能性のあるコードは、nothrow の保証を提供していません。おそらく、呼び出し元がダフ データを与えないように少し再設計することで、そうすることができます。ただし、関数が他の理由で既に例外をスローする必要がある場合は、ハードウェア トラップのために例外をスローしても、事態は悪化しない可能性があります。

注目すべき特殊なケースの 1 つは、メモリ割り当てです。.NET がこれを行うかどうかはわかりませんが、Linux では、割り当てに十分な仮想アドレス空間がない場合にのみ割り当てが失敗します。物理メモリは最初の使用時にコミットされ、十分でない場合はハードウェア例外が発生します。メモリ割り当ては失敗時に std::bad_alloc をスローすると想定されており、実装は標準のこの要件の実装に失敗するため場合によっては、ハードウェア例外をソフトウェアに変換することが正しいことです。ただし、そのハードウェア例外は予期しない場所で発生する可能性があるため (スローされないと思われるルーチンを含む)、適切に処理することはまだ不可能な場合があります。これが、スローの代わりに Linux コア ダンプが発生する理由です。実際には、完全に初期化されたものはすべてそのコンストラクターをクラッシュさせます。これは多くの場合、ソフトウェア例外が代わりに役立つ割り当てに十分近いものです。

于 2008-12-09T15:06:38.533 に答える