次のコードは、私が現時点で持っている問題をまとめたものです。私の現在の実行フローは以下の通りです。私はGCC 4.3で動作しています。SetJmp/LongJmp:なぜこれがセグメンテーションを投げているのですか?
jmp_buf a_buf;
jmp_buf b_buf;
void b_helper()
{
printf("entering b_helper");
if(setjmp(b_buf) == 0)
{
printf("longjmping to a_buf");
longjmp(a_buf, 1);
}
printf("returning from b_helper");
return; //segfaults right here
}
void b()
{
b_helper();
}
void a()
{
printf("setjmping a_buf");
if(setjmp(a_buf) == 0)
{
printf("calling b");
b();
}
printf("longjmping to b_buf");
longjmp(b_buf, 1);
}
int main()
{
a();
}
上記の実行フローは、b_helperでリターンした直後にsegfaultを作成します。 b_helperスタックフレームだけが有効で、その下のスタックが消去されているかのようです。
これはなぜ起こっているのですか?私はそれが未使用のスタックフレームや何かを消去しているGCCの最適化だと思っています。
ありがとうございました。
スタックフレームをlongjmpにする方法はありますか?スタックからbをb_helperにコピーしてヒープにコピーし、そこから実行することは可能ですか? また、コールスタックをジャンプアップした後、b_bufによって参照されるスタックフレームが有効でなくなったのはなぜですか? – jameszhao00
スタックの一部が解放されると、完全に無効になります(他の関数呼び出し、割り込み、またはメモリを上書きする可能性のあるもの)。 –
'longjmp()'を "extended return"と考えることができます。成功した 'longjmp()'は一連の連続した戻り値のように機能し、対応する 'setjmp()'に達するまで呼び出しスタックを解放します。コールスタックフレームが解放されると、それらはもはや有効ではなくなります。これは、コールスタックがどこか別の場所にジャンプした後も有効であるコルーチン(例:Modula-2)や継続(たとえばScheme)の実装とは対照的です。CとC++は、複数の独立した呼び出しスタックを作成する場所でスレッドを使用しない限り、*単一の線形呼び出しスタックのみをサポートします*。 –