在setjmp.h中定义的C中的非本地跳转如何工作?

时间:2013-05-19 15:17:32

标签: c longjmp setjmp

C参考手册,附录B描述了一些名为非本地跳转的函数setjmplongjmp。除了setjmp保存状态信息和longjmp恢复state的基本理解之外,我还无法理解此功能的确切流程和用例。

那么,这个功能究竟完成了什么以及它在哪里有用?

1 个答案:

答案 0 :(得分:6)

至于控制流:setjmp返回两次,longjmp永不返回。当您第一次调用setjmp时,为了存储环境,它返回零,当您调用longjmp时,控制流将从setjmp返回并返回值论证。

(注意setjmp实际上不需要是函数;它可能是一个宏。longjmp是一个函数。)

用例通常被称为“错误处理”,“不使用这些功能”。

这是一个小控制流示例:

jmp_buf env;

void foo()
{
    longjmp(&env, 10);                      +---->----+
}                                           |         |
                                            |         |
int main()              (entry)---+         ^         V
{                                 |         |         |
    if(setjmp(&env) == 0)         | (= 0)   |         | (= 10)
    {                             |         ^         |
        foo();                    +---->----+         |
    }                                                 +---->----+
    else                                                        |
    {                                                           |
        return 0;                                               +--- (end)
    }
}

注意:

  • 您无法将0传递给longjmp。如果您这样做,1会返回setjmp

  • 您不得在相应的setjmp之前从调用longjmp的函数返回。换句话说,longjmp只能在调用堆栈中调用上面的 setjmp

  • (感谢@wildplasser :)您实际上无法存储 setjmp的结果。如果您想以多种不同的方式返回,可以使用switch,但是:

    switch (setjmp(&env))
    {
    case 0:   // first call
    case 2:   // returned from longjmp(&env, 2)
    case 5:   // returned from longjmp(&env, 5)
    // etc.
    }