3

jpeglibでは、 setjmp/longjmp を使用してカスタム エラー処理を実装する必要があります。

setjmp/longjmp が c++ でうまく機能しないと言われているリソースはたくさんあります (たとえば、この質問の回答は RAII と一緒に使用すると言っています) が、この質問への回答は、デストラクタが呼び出されると述べています。

私はこの例を持っています(ここから取られ、少し変更されました):

#include <iostream>
#include <csetjmp>

std::jmp_buf jump_buffer;

struct A
{
    A(){std::cout<<"A()"<<std::endl;}
    ~A(){std::cout<<"~A()"<<std::endl;}
};

void a(int count) 
{
    std::cout << "a(" << count << ") called\n";
    std::longjmp(jump_buffer, count+1);  // setjump() will return count+1
}

int main()
{
    // is this object safely destroyed?
    A obj;

    int count = setjmp(jump_buffer);
    if (count != 9) {
        a(count);
    }
}

この例では、(予想どおり) デストラクタが呼び出されますが、それは標準的な動作ですか? それとも、コンパイラの拡張機能ですか、それとも単純な UB ですか?


出力:

A()
a(0) called
a(1) called
a(2) called
a(3) called
a(4) called
a(5) called
a(6) called
a(7) called
a(8) called
~A()
4

1 に答える 1

7

デストラクタが呼び出されるかどうかによっては、未定義の動作になる可能性があります。これは、同じ制御の転送を実行するための例外でした。C++03 で。セクションから18.7 Other runtime support, paragraph 4:

この国際標準では、関数シグネチャのlongjmp(jmp_buf jbuf, int val)動作がより制限されています。プログラム内の別の (宛先) ポイントに制御を転送するスローされた例外によって自動オブジェクトが破棄される場合、同じ (宛先) ポイントに制御を転送するスロー ポイントでの呼び出しlongjmp(jbuf, val)の動作は未定義です。

C ++ 11にも同様の言語があります:

この国際標準では、関数シグネチャのlongjmp(jmp_buf jbuf, int val)動作がより制限されています。andをandsetjmp/longjmpに置き換えると、呼び出しペアの動作が未定義になり、自動オブジェクトの非自明なデストラクタが呼び出されます。setjmplongjmpcatchthrow

ただし、この特定のコードの移行中に呼び出されるデストラクタはないように見えるので、安全だと思います。


ここで、作成を の後に移動するようにコードを変更するsetjmpと、未定義の動作になります。私のセットアップ(Debianのgcc 4.4.5)では、次のコード(他のすべては質問と同じです):

int main() {
    int count = setjmp (jump_buffer);
    A obj;
    if (count != 4) a (count);
}

結果は次のようになります。

A()
a(0) called
A()
a(1) called
A()
a(2) called
A()
a(3) called
A()
~A()

また、デストラクタがジャンプの一部として呼び出されていないことがわかりますが、定義されていないため、システムによってはそうである可能性があります。


肝心なのは、デストラクタを呼び出すthrow/catch保証がないため、リージョン A からリージョン B にジャンプするべきではありません。longjmp

setjmp/longjmp実際、 C++ ではまったく使うべきではないと言う人もいますが、私自身もその傾向があります。Cでもその必要性を見つけるのに苦労しています。

MS-DOS の下で Turbo C に共同スレッドを実装するために、私のキャリア全体 (そしてそれは長いキャリアです) で一度使用したと思います。私はそれを使ったことがもう1回考えられません。用途がないわけではありませんが、かなりレアです。

于 2013-04-29T06:37:30.403 に答える