catch(Exception)
C++ では、( C#のように) 1 回のキャッチですべての種類の例外をキャッチしようとしています。それはどのように行われますか?さらに、ゼロ除算の例外をキャッチするにはどうすればよいでしょうか。
9 に答える
catch (...)
{
// Handle exceptions not covered.
}
重要な考慮事項:
- より良いアプローチは、考えられるすべての例外ではなく、実際に回復できる特定の種類の例外をキャッチすることです。
- catch(...) は、確実に回復できない特定の重大なシステム レベルの例外 (コンパイラによって異なります) もキャッチします。このようにそれらを捕まえ、飲み込んで続行すると、プログラムでさらに深刻な問題が発生する可能性があります。
- コンテキストによっては、例外が再スローされる場合、catch(...) の使用が許容される場合があります。この場合、すべての有用なローカル状態情報をログに記録してから、例外を再スローして、それが伝播できるようにします。ただし、このルートを選択する場合は、 RAII パターンをよく読んでください。
本当に、間違いなく、最も証明可能な場合を除き、catch (...) (つまり、省略記号付きの catch) を使用したくありません。
この理由は、一部のコンパイラ (Visual C++ 6 が最も一般的) は、セグメンテーション違反やその他の非常に悪い状態などのエラーを、catch (...) を使用して喜んで処理できる例外に変換するためです。クラッシュはもう見られないので、これは非常に悪いことです。
技術的には、はい、ゼロ除算をキャッチすることもできます (そのためには「StackOverflow」が必要です) が、そもそもそのような除算を避ける必要があります。
代わりに、次の操作を行います。
- 予想される例外の種類が実際にわかっている場合は、それらのタイプのみをキャッチし、それ以上はキャッチしません。
- 自分で例外をスローする必要があり、スローするすべての例外をキャッチする必要がある場合は、これらの例外を std::exception から派生させ (Adam Pierce が提案したように)、それをキャッチします。
Windows を使用していて、ゼロ除算やアクセス違反などのエラーを処理する必要がある場合は、構造化例外トランスレータを使用できます。次に、トランスレーター内で C++ 例外をスローできます。
void myTranslator(unsigned code, EXCEPTION_POINTERS*)
{
throw std::exception(<appropriate string here>);
}
_set_se_translator(myTranslator);
コードはエラーの内容を示していることに注意してください。また、/EHa オプションを使用してコンパイルする必要があります (C/C++ -> コード生成 -> C/C++ 例外を有効にする = SEH 例外ではい)。
それが意味を成さない場合は、[_set_se_translator]( http://msdn.microsoft.com/en-us/library/5z4bw5h5(VS.80).aspx)のドキュメントを確認してください。
OS の例外を含むすべての例外をキャッチすることが本当に必要な場合は、コンパイラと OS を確認する必要があります。たとえば、Windows では、おそらく "__try" キーワードまたはコンパイラ スイッチを使用して、"try/catch" で SEH 例外をキャッチするか、またはその両方を実行します。
すべてのカスタム例外クラスが std::exception から継承されるようにすると、std::exception を簡単にキャッチできます。コード例を次に示します。
class WidgetError
: public std::exception
{
public:
WidgetError()
{ }
virtual ~WidgetError() throw()
{ }
virtual const char *what() const throw()
{
return "You got you a widget error!";
}
};
もちろん、 を使用することもできますが、catch (...) { /* code here */ }
実際には何をしたいかによって異なります。C++ には決定論的なデストラクタがあります (ファイナライズのゴミはありません)。そのため、一掃したい場合は、RAII を使用するのが正しい方法です。
例えば。それ以外の:
void myfunc()
{
void* h = get_handle_that_must_be_released();
try { random_func(h); }
catch (...) { release_object(h); throw; }
release_object(h);
}
次のようにします。
#include<boost/shared_ptr.hpp>
void my_func()
{
boost::shared_ptr<void> h(get_handle_that_must_be_released(), release_object);
random_func(h.get());
}
ブーストを使用しない場合は、デストラクタを使用して独自のクラスを作成します。
C++ では、標準で 0 除算の例外が定義されておらず、実装によって例外がスローされない傾向があります。
私の記憶が正しければ (C++ を見てからしばらく経ちます)、次のようにすればうまくいくと思います。
try
{
// some code
}
catch(...)
{
// catch anything
}
簡単なグーグル(http://www.oreillynet.com/pub/a/network/2003/05/05/cpluspocketref.html)は私が正しいことを証明しているようです。