2013-04-19 1 views
9

自分の言語で作業しているときに、フロー制御で面白いシナリオが発生しました。 breakステートメントの処理中に例外がスローされた場合はどうなりますか。 GCCはブレークフローが失われたと信じているようだが、標準は何が起こるべきかについていくらか沈黙しているようだ。ブレーク/継続/リターンは例外によって中断されるべきですか?

例えば、次のプログラムは実際に何をすべきですか?

#include <iostream> 
using namespace std; 

struct maybe_fail { 
    bool fail; 
    ~maybe_fail() { 
     if(fail) 
      throw 1; 
    } 
}; 

int main() { 
    for(int i=0; i < 6; ++i) { 
     cout << "Loop: " << i << endl; 

     try { 
      maybe_fail mf; 
      mf.fail = i % 2; 
      if(i == 3) 
       break; 

     } catch(int) { 
      cout << "Caught" << endl; 
     } 
    } 
    return 0; 
} 

continueが(それを見てキャッチした後、出力を追加)されますようreturnも、ブロックされることに注意してください。ブロックの外にgotoへの試みもキャッチされます。

正しいフローは何ですか?標準はこれに対処していないようです:jump文のセクション6.6は言及しません。また、例外処理のセクション15も言及しません。デストラクタの例外はひどく悪いものですが、BOOST_SCOPE_EXITのようなものをdefer文に使用している場合は、この動作が非常に重要になる可能性があります。

おそらく、JavaとPythonでは同じ流れが起こるため、命令型言語には一貫性があるようです。

+0

あなたの質問はC++ FAQのアドバイスであるようです:http://www.parashift.com/c++-faq-lite/dtors-shouldnt-throw.html基本的に、例外をスローラに投げ込まないでください。 FAQのこの質問は、「二重例外処理」状況にある場合に 'terminate()'がどのように呼び出されるのかを示していますが、あなたの例ではそれを行うのが悪いとのアドバイスを続けているようです。 –

+1

@Kevin、そのアドバイスは、どの言語(C++のBOOST_SCOPE_EXITも含む)の "defer"のようなステートメントにも拡張されます。 –

+0

どのように行動を解釈するでしょうか?デストラクタで例外を投げて、何を? – bdwain

答えて

4

がこれは例外をスロー15.1で覆われている:例外がスローされる場合

2、制御は、整合型(15.3)と最も近いハンドラに転送されます。 "nearest"は、tryキーワード に続くcompound-statementまたはctor-initializerが、制御スレッドによって最後に入力されたがまだ終了していないハンドラを意味します。

制御が例外ハンドラに転送されると、そこから制御が移ります。コードがbreakの真中にあったことを「覚えて」いるメカニズムはなく、何らかの形で例外が処理された後にコードが再開されます。

+0

これは十分明確であるとは確信していません。 6.6節では、ジャンプ文に示されたようにジャンプ文が必要であり、そのフローの中断について言及していないことを考慮してください。つまり、あなたが述べている要件とジャンプのリユアメントが矛盾していると思います。 –

+0

@ edA-qamort-ora-y「ジャンプが起こる前にデストラクタが呼び出される」という標準への参照は、この質問に答えますか? –

+0

@ edA-qamort-ora-y:正直言って、6.6(特に2番目のパラグラフ)を見ていると、あいまいさを見ているのか分からない。 – NPE

0

スタンドナードの具体的な文言に拘らず、私はそれがあいまいだと言うつもりです。テキストは、これらの状況を意図するフローを特定するのに不十分である。私たちが現在行っているコンベンションは、コンパイラがどのように書かれているかに起因するものです。

私のブログトピックHow to catch a "return" statementを参照してください。

関連する問題