2009-06-24 7 views
36

C++は、例えば、チェック例外の構文を提供します:C++の例外がコンパイラによってチェックされないのはなぜですか?

void G() throw(Exception); 
void f() throw(); 

ただし、Visual C++コンパイラがそれらをチェックしません。スローフラグは単に無視されます。私の意見では、これは例外機能を使用不可能にします。だから私の質問は:は、コンパイラが例外が正しくキャッチ/再スムーズされているかどうかをチェックする方法はありますか?たとえば、Visual C++プラグインまたは別のC++コンパイラ。

PS。コンパイラが例外が正しくキャッチされているかどうかをチェックしたい場合は、がスローされないことを明示的に示しても、のすべての関数呼び出しをキャッチする必要があります。

更新: Visual C++コンパイラは、throw()でマークされた関数をスローするときに警告を表示します。これは素晴らしいことですが、残念ながら、スローする可能性があるサブルーチンを呼び出すと警告が表示されません。たとえば:

void f() throw(int) { throw int(13); } 
void h() throw() { g(); } //no warning here! 
+0

私はC++のチェック例外について聞いたことがありませんが、今は例外仕様について、Visual C++はあまり気にしません。http://msdn.microsoft.com/ ja-jp/library/wfa0edys.aspx – Skurmedel

+1

Visual C++ではそれを無視していません...関数の最後にthrow()を追加すると、Visual C++はその関数が例えば関数が実際にスローした場合、何かが起こる可能性があります。スタンダードでは、関数がマークされている場合、例外のためにthrow()が終了し、std :: unexpected()は通常std :: bad_exceptionをスローします。これは「何かが起こること」とはまったく異なります。 – Doug

+0

例外仕様がコンパイラに対するヒントであり、何かを行う必要性ではない場合、潜在的に有用なものになります。標準的な行動は、私の意見では、役に立たない。 –

答えて

29

例外仕様はC++ではかなり役に立たない。

他の例外がスローされないことを強制ではないが、グローバル関数unexpected()が例外仕様を使用して(設定可能)

と呼ばれるだけであることは、主に自分(または自分の仲間を)deludingに沸きますセキュリティの誤った感覚簡単に気にしない方がいいです。

+0

"Impossible"はかなり強い主張です。テンプレートで例外仕様の実施が不可能なのはなぜですか? –

+0

それについて考えてみて、当然ですが、私がどこにいるのか分かりません。段落を削除しました。 – Pieter

+1

完全な誤った議論です。 C++(Javaや他のほとんどの現代言語と違って)はコンパイル時ではなく実行時に例外仕様をチェックします。残念なことに例外的な仕様のこの実験は(スローされていなくても)機能しませんでした。 –

14

はこれを見ている:

http://www.gotw.ca/publications/mill22.htm

基本的に例外仕様は使用できない/実行不可能ですが、それは例外が実行不可能ことはありません。

あなたの質問には、スローされたすべての型がコードのどこかでキャッチされていることをコンパイラに確認させる方法がないので、コンパイル単位ではこれを難しくし、使用するコードライブラリ(トップレベルはコンパイル時に利用できません)に保存されます。すべてがキャッチされていることを確認したい場合は、コードの最上部にキャッチ(...)を貼り付けます。

+1

あなたの答えをありがとう。トップレベルのcatch(...)の問題は、C++では何が起きたかについてほとんど情報が得られないということです。タイプ情報も呼び出しスタックもありません。この問題は、単一のタイプの例外を非常に規則的な方法でスローすることで回避できますが、エラーが発生しやすくなります。 –

+1

@ Dimitri:私は、std :: exceptionから派生した例外を常にスローします。これを行うには大量の規律は必要ありません。 – Patrick

0

MSVCのインストールが不十分であることを確認することはできませんが、コンパイラがthrow()の指定を無視しているのは本当ですか?

This MSDN pageは、Microsoftがthrow()を認識しており、コンパイラが正しく処理することを期待していることを示しています。さて、ほとんどの場合、ANSI/ISO標準からどのように離れていくかについての注意を参照してください。

編集:実際には、私はPatrickに同意します。例外の仕様はほとんど役に立たないです。

8

標準でそう言います。例外宣言は、他に例外がスローされることを意味しません。宣言されていない例外がスローされると、unexpected()という特別なグローバル関数が呼び出され、デフォルトでプログラムが終了します。標準的な振る舞いはそれほど役に立ちませんので、関数内での例外の宣言はお勧めできません(空の例外リストを除いて)。

9

extern void f() throw (class Mystery); 
void g() throw() { 
    f() ; 
} 

...として例をランタイムに前に検出するには...あなたは静的解析を必要としています。はい、コンパイラは多くの静的解析を行っていますが、標準が「スローが一致しない場合は予期しない:: unexpectedを発生させる」ため、指定子と一致しないオブジェクトをスローするルーチンを書くことは完全に合法ですコンパイラの実装者は、警告も発言もしません。警告サービスを提供することを主張

静的解析ツールには、Gimpel Softwareのlint for C++ ...

キャッチされない例外 '名前' 機能のためではないのスロー-list 'のシンボル'

と、先の質問にthis answerによると、QA C++

37

面白いことに、Javaは例外をチェックしており、Javaプログラマも例外をチェックしています。

C++で

例外仕様は3つの理由のために役に立たない:

1 C++例外仕様は、最適化を阻害します。

例外をスローした場合、コンパイラは、例外をスローするときにスタックのアンワインド中に関数の例外仕様に一致するかどうかをチェックするために余分なコードを挿入します。あなたのプログラムを遅くする方法。

2. C++の例外仕様は、コンパイラ、適用されません

を限りコンパイラが懸念されるとして、以下が構文的に正しいです:

void AStupidFunction() throw() 
{ 
    throw 42; 
} 

さらに悪い何が違反した場合、有益な何も起こりません例外仕様。あなたのプログラムはちょうど終了します!

3. C++の例外仕様は、関数の署名の一部です。

仮想関数を持つ基本クラスがあり、それをオーバーライドしようとすると、例外の仕様は正確に一致する必要があります。だから、先に計画する方が良いでしょう。それはまだ痛みです。

struct A 
{ 
    virtual int value() const throw() {return 10;} 
} 

struct B : public A 
{ 
    virtual int value() const {return functionThatCanThrow();} // ERROR! 
} 

例外仕様には、これらの問題があり、それらを使用するための利得は最小です。対照的に、例外仕様を完全に避けると、コーディングがより簡単になり、このようなことは避けられます。

+0

ニースの答え!ありがとう。 –

+0

私たちは "投げ42"を回避することができますか?問題? – Anuj

関連する問題