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;
}

returnaも a と同様にブロックされることに注意してくださいcontinue(それを確認するには、catch の後に出力を追加します)。ブロックの外への試みgotoもキャッチされます。

正しい流れとは?標準はこれに対処していないようです。ジャンプステートメントに関するセクション6.6は言及しておらず、例外処理に関するセクション15も言及していません。デストラクタの例外がひどく悪い形であることは理解していますが、遅延ステートメントに BOOST_SCOPE_EXIT のようなものを使用している場合、この動作は非常に重要になる可能性があります。

おそらく興味深いことに、Java と Python で同じフローが発生するため、少なくとも命令型言語にはある程度の一貫性があるようです。

4

2 に答える 2

4

これは、15.1 例外のスローで説明されています。

2 例外がスローされると、制御は一致する型 (15.3) を持つ最も近いハンドラーに転送されます。「最も近い」とは、try キーワードに続く複合ステートメントまたは ctor-initializer が制御スレッドによって最後に入力され、まだ終了していないハンドラーを意味します。

制御が例外ハンドラに渡されると、そこから続行されます。コードが途中であったことを「記憶」しbreak、例外が処理された後に何らかの方法でそれを再開するメカニズムはありません。

于 2013-04-19T04:10:14.803 に答える
0

標準の特定の文言に照らして、私はそれが曖昧であると言うつもりです. これらの状況で意図された流れを特定するには、テキストが不十分です。コンパイラがどのように記述されているかによって、現在の慣例が単なる偶発的なものである可能性は十分にあります。

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

于 2013-05-09T10:22:58.407 に答える