【问题标题】:Why does this setjmp program print a 5?为什么这个 setjmp 程序打印一个 5?
【发布时间】:2013-11-29 16:15:37
【问题描述】:

下面的代码只是打印“5”

#include <iostream>
#include <setjmp.h>

static jmp_buf buf;

float funcB()
{
    setjmp(buf);
    return 1.6f;
}

int funcA()
{
    longjmp(buf,5);
    std::cout<<"b";
    return 2;
}

int main()
{
    funcB();
    std::cout<<funcA();
}

但这没有任何意义,因为 setjmp 返回 5,而不是任何一个函数...... 别担心,我没有在任何地方使用此代码,我只是好奇!

【问题讨论】:

  • 注意:在 C++ 中使用 setjmp/longjmp 是错误的。我们在这里有投掷和接球。
  • 同意,我只是好奇他们会搞砸多少
  • @foips 它们(几乎总是)导致未定义的行为,这几乎是你所能得到的。

标签: c++ setjmp


【解决方案1】:

您正在尝试做的事情在documentation 中被明确指定为未定义的行为:

longjmp() 函数使用对应的jmp_buf 参数恢复同一线程中最近一次调用setjmp() 保存的环境。如果没有这样的调用,或者如果包含setjmp() 调用的函数在此期间终止了执行,则行为未定义。

由于在funcA 中调用longjmp 之前调用setjmp(即funcB)的函数已退出,因此行为未定义(it crashes on ideone)。

【讨论】:

  • 嗯,我明白了。但是,5 仍然来自 longjmp 值参数,并随该值而变化。看看为什么会在程序组装方面发生这种情况会很有趣
  • 还要注意,我是用clang编译的
  • @foips 发生这种情况的一种方法是编译器通过指定的寄存器返回值。由于funcB 返回一个float,将1.6f 加载到返回寄存器中不会更改用于返回整数结果的寄存器中的值。这就是为什么5funcA(错误地)在混淆longjmp 之后返回时保留在返回寄存器中的原因。更改优化级别或使 funcB 返回一个整数可能会改变观察到的未定义行为。
  • 啊,这很好解释。谢谢!
【解决方案2】:

您不能使用 longjmp 返回已退出的函数。换句话说,longjmp 不会为您恢复堆栈。见here

你需要的是一种类似scheme的语言,在这种情况下做这种事情是完全正常的。

【讨论】:

  • 代码编译运行,你的意思是什么? (啊,通过您的编辑,我明白您在说什么)
  • @foips 您正在以非法方式使用 setjmp/longjmp,因此您的程序有未定义的行为。就像你取消引用了一个 NULL 指针或其他东西一样。
【解决方案3】:

您使用的任何编译器似乎都在严格解释 setjmplongjmp 所做的事情:

此宏可能会多次返回:第一次,直接返回 调用;在这种情况下,它总是返回零。当 longjmp 是 使用设置为 env 的信息调用,宏再次返回;这 时间它返回作为第二个参数传递给 longjmp 的值,如果这个 不为零,如果为零,则为 1。

来自here

因为它是 UB,它可以做到这一点,点披萨,结束世界……任何事情都是有效的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-26
    • 2011-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多