SetJmp/LongJmp:为什么会抛出段错误?

发布于 2024-08-04 03:00:58 字数 717 浏览 3 评论 0原文

下面的代码总结了我目前遇到的问题。我当前的执行流程如下,我在 GCC 4.3 中运行。

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 返回后立即创建了一个段错误。几乎就好像只有 b_helper 堆栈帧有效,并且它下面的堆栈被擦除。

谁能解释为什么会发生这种情况?我猜这是一个 GCC 优化,正在删除未使用的堆栈帧或其他东西。

谢谢。

The following code summarizes the problem I have at the moment. My current execution flow is as follows and a I'm running in GCC 4.3.

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

The above execution flow creates a segfault right after the return in b_helper. It's almost as if only the b_helper stack frame is valid, and the stacks below it are erased.

Can anyone explain why this is happening? I'm guessing it's a GCC optimization that's erasing unused stack frames or something.

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

十级心震 2024-08-11 03:00:59

您只能longjmp()备份调用堆栈。对 longjmp(b_buf, 1) 的调用是开始出错的地方,因为 b_buf 引用的堆栈帧在 longjmp(a_buf) 之后不再存在

来自 longjmp 的文档:

在调用 setjmp() 例程的例程返回后,不能再调用 longjmp() 例程。

这包括通过函数的longjmp()“返回”。

You can only longjmp() back up the call stack. The call to longjmp(b_buf, 1) is where things start to go wrong, because the stack frame referenced by b_buf no longer exists after the longjmp(a_buf).

From the documentation for longjmp:

The longjmp() routines may not be called after the routine which called the setjmp() routines returns.

This includes "returning" through a longjmp() out of the function.

梦初启 2024-08-11 03:00:59

标准对于 longjmp() 是这么说的(7.13.2.1 longjmp 函数):

longjmp 函数恢复最近调用保存的环境
setjmp 宏在程序的同一调用中具有相应的
jmp_buf 参数。如果没有这样的调用,或者如果函数包含
setjmp 宏的调用已​​临时终止执行

脚注对此进行了澄清:

例如,通过执行 return 语句或因为另一个 longjmp 调用导致了
转移到嵌套调用集中较早的函数中的 setjmp 调用。

所以你不能 longjmp() back &跨嵌套的 setjmp/longjmp 集。

The standard says this about longjmp() (7.13.2.1 The longjmp function):

The longjmp function restores the environment saved by the most recent invocation of
the setjmp macro in the same invocation of the program with the corresponding
jmp_buf argument. If there has been no such invocation, or if the function containing
the invocation of the setjmp macro has terminated execution in the interim

with a footnote that clarifies this a bit:

For example, by executing a return statement or because another longjmp call has caused a
transfer to a setjmp invocation in a function earlier in the set of nested calls.

So you can't longjmp() back & forth across nested setjmp/longjmp sets.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文