`longjmp`进入终止函数

时间:2014-01-15 23:49:53

标签: c linux

Michael Kerrisk在“Linux编程接口”中的练习6.2问道:

  

编写程序,看看如果我们尝试longjmp()进入已经终止的函数会发生什么。

我在想这个程序应该可以解决问题:

#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>

static jmp_buf env;

void foo (void);
void bar (void);
void baz (void);

int
main (int argc, char *argv[])
{
    foo();
    bar();

    exit(EXIT_SUCCESS);
}

void
foo (void)
{
    printf("foo start\n");

    switch (setjmp(env)) {
    case 0:
        printf("foo branch 0\n");
        break;
    case 1:
        printf("foo branch 1\n");
        break;
    }

    printf("foo end\n");
    return;
}

void
bar (void)
{
    printf("bar start\n");

    baz();

    printf("bar end\n");
    return;
}

void
baz (void)
{
    printf("baz start\n");

    longjmp(env, 1);

    printf("baz end\n");
    return;
}

相反,这会打印:

$ ./setjmp
foo start
foo branch 0
foo end
bar start
baz start
foo branch 1
foo end

也就是说,如果foo没有终止,我会期望的行为。这是为什么?如何修改我的程序以使longjmp成为终止函数?

1 个答案:

答案 0 :(得分:2)

Wikipedia。拿一粒盐。

  

跳转到已通过return或longjmp终止的函数   未定义。[6]但是,longjmp的大多数实现都没有   在执行跳转时专门销毁局部变量。从那以后   上下文一直存在,直到它的局部变量被删除,它可以   实际上是通过setjmp恢复的。

幸运的是,他们引用了(尽管是旧的)标准。

§7.13.2.1/ 2

  

longjmp函数恢复最近保存的环境   在同一个程序调用中调用setjmp宏   使用相应的jmp_buf参数。如果没有这样的话   调用,或者如果函数包含setjmp的调用   宏已在临时中终止执行 211),或者如果是   setjmp宏的调用是在标识符的范围内   具有可变修改类型和执行已经留下了该范围   临时,行为未定义。

     

211)例如,通过执行return语句或另一个语句   longjmp调用导致转移到a中的setjmp调用   在嵌套调用集的早期函数。