Back to Top

函数 longjmp

longjmp 可以实现C语言的非局部跳转, 在栈上跳过若干调用帧, 返回到某一个调用过setjmp的函数中.

当执行longjmp返回后, 大多数实现并不回滚自动变量和寄存器变量, 标准中称它们的值是不确定.

如果有一个自动变量,又不想使其值回滚,则可定义其为具有volatile属性. 声明为全局变量或静态变量的值在执行longjump时保持不变.

跳回前几行

void test_jmp_above_lines() 
{
    static jmp_buf buf;
    int i = 123456;
    int ret = 0;

    printf("test_jmp_above_lines\tbefore jmp:%d\n", i);

    ret = setjmp(buf);
    if (ret == 0) {
        i = 10001;
        printf("test_jmp_above_lines\tbefore jmp:%d\n", i);
        longjmp(buf, 10);
    } else {
        printf("test_jmp_above_lines\tafter jmp:%d ret:%d\n", i, ret);
    }
}
/*
test_jmp_above_lines    before jmp:123456
test_jmp_above_lines    before jmp:10001
test_jmp_above_lines    after jmp:10001 ret:10
*/

跳回已经执行完成的函数

void test_jmp_exit_func1(jmp_buf* buf1, jmp_buf* buf2)
{
    int i = 123456;
    int ret = 0;

    printf("test_jmp_exit_func1\tbefore jmp1:%d@%p\n", i, &i);

    ret = setjmp(*buf1);
    if (ret == 0)
    {
        i = 10001;
        printf("test_jmp_exit_func1\tbefore jmp1:%d@%p\n", i, &i);
    }
    else
    {
        printf("test_jmp_exit_func1\tafter jmp1:%d@%p ret:%d@%p\n", i, &i, ret, &ret);
    }

    ret = setjmp(*buf2);
    if (ret == 0)
    {
        i = 90009;
        printf("test_jmp_exit_func1\tbefore jmp2:%d@%p\n", i, &i);
    }
    else
    {
        printf("test_jmp_exit_func1\tafter jmp2:%d@%p ret:%d@%p\n", i, &i, ret, &ret);
    }
    printf("test_jmp_exit_func1\texit:%d@%p ret:%d@%p\n", i, &i, ret, &ret);
}

void test_jmp_exit_func() 
{
    static jmp_buf buf1;
    static jmp_buf buf2;
    int longjmp_flag = 0;
    test_jmp_exit_func1(&buf1, &buf2);
    longjmp_flag++;

    if (longjmp_flag == 1)
        longjmp(buf1, 6);
}
/*
test_jmp_exit_func1     before jmp1:123456@0x7ffe9365161c
test_jmp_exit_func1     before jmp1:10001@0x7ffe9365161c
test_jmp_exit_func1     before jmp2:90009@0x7ffe9365161c
test_jmp_exit_func1     exit:90009@0x7ffe9365161c ret:0@0x7ffe93651618
test_jmp_exit_func1     after jmp1:32576@0x7ffe9365161c ret:6@0x7ffe93651618
test_jmp_exit_func1     before jmp2:90009@0x7ffe9365161c
test_jmp_exit_func1     exit:90009@0x7ffe9365161c ret:0@0x7ffe93651618
*/