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
*/