1

スタックの巻き戻し中に、例外で参照されるローカル変数はどうなりますか? 次のコードを検討してください。

class bar;
class my_error
{
public:
    my_error(const bar& bar) : _bar(bar) {}
    const bar& get_bar() const { return _bar; }

private:
    const bar& _bar;
}


...

bar some_local_object(...);
if (!foo()) {
   throw my_error(some_local_object);
}

...

try {
    g();
} catch (my_error& e) {
    e.get_bar()
    ...
}

some_local_objectはどうなりますか? スタックの巻き戻し中に破棄されるべきではありませんか? 例に示されているように、安全に使用できますか?

追加の質問

すでに回答されているように、このコードは未定義の動作につながります。それに対する私の2番目の質問は次のとおりです。

ローカル オブジェクトへの参照を渡すことも、そのコピーを作成することも許可されていない場合、まれに bad_alloc が発生する可能性があるためです (これが、gcc 標準ライブラリに意味のあるエラー メッセージ、つまり map.at がない理由だと思います)。 what() が「map.at」を返す例外をスローする場合)、追加情報を渡すための適切な戦略は何ですか? 複数の文字列を結合しても、エラー メッセージの作成中に理論的には bad_alloc が発生する可能性があることに注意してください。すなわち:

void do_something(const key& k, ....)
{
    ...
    if (!foo(k)) {
        std::ostringstream os;
        os << "Key " << k << " not found"; // could throw bad_alloc
        throw std::runtime_error(os.str()); 
    }
    // another approcach
    if (!foo(k)) {
        throw key_not_found(k); // also bad, because exception could outlive k
    }
}
4

2 に答える 2

4

動作は、スタック上の変数への参照を返す場合と同じです。オブジェクトは、使用する前に破棄されます。つまり、例外がキャッチされるまでに、参照されたオブジェクトは破棄され、参照へのすべてのアクセスは未定義の動作になります。

標準の関連条項は、15.2 [except.ctor] パラグラフ 1 です。

例外がスローされたポイントからハンドラーに制御が渡されると、try ブロックに入ってから構築されたすべての自動オブジェクトに対してデストラクタが呼び出されます。自動オブジェクトは、構築完了の逆の順序で破壊されます。

于 2014-12-06T22:31:30.520 に答える
3

ローカル オブジェクトは、スタックの巻き戻し中に破棄されます。その後、参照は無効になり、ぶら下がり参照になります。つまり、参照が使用されるような例外オブジェクトの検査には、未定義の動作があります。

于 2014-12-06T22:31:39.183 に答える