Linux setjmp & longjmp

错误处理是任何语言都需要解决的问题,任何语言都不能保证100%的正确运行,都需要异常机制的存在,例如c++ 的try ... catch , c 语言因此提供 setjmp 与 longjmp 来实现 内存堆栈的跳转。 实现一种非本地局部跳转的机制, 本地局部跳转如:goto



函数定义

1
2
int setjmp(jmp_buf jb);
void longjmp(jmp_buf jb, int r);
  • setjmp 用于保存程序的运行时堆栈环境 cs:ip 寄存器;
  • longjmp 恢复先前程序中调用setjmp 函数所保存的堆栈环境;

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
[Postgres@yfslcentos71 code]$ cat jmp.c 
#include <stdio.h>
#include <stdlib.h>
#include <setjmp.h>

jmp_buf jb;

void f1()
{
printf("进入f1()\n");
//if(0/*正确执行*/){ }
if(1/*正确执行*/){
printf("F1 正确执行\n");
}
else {
printf("F1 执行错误\n");
longjmp(jb,1);
}
printf("退出f1()\n");
}
void f2()
{
printf("进入f2()\n");
if(0/*正确执行*/) {
printf("F2 正确执行\n");
}
else {
printf("F2 执行错误\n");
longjmp(jb, 2);
}
printf("退出f2()\n");
}

int main()
{
int r = setjmp(jb);
printf("longjmp 返回值 r = %d\n", r);
if(r==0){
f1();
f2();
}else if(r==1){
printf("else if 1 返回值 r = %d\n", r);
printf("处理错误1\n");
exit(1);
}else if(r==2){
printf("else if 2 返回值 r = %d\n", r);
printf("处理错误2\n");
exit(2);
}
printf("所有函数执行完毕, 程序结束\n");
return 0;
}

输出结果

1
2
3
4
5
6
7
8
9
10
[Postgres@yfslcentos71 code]$ ./jmp 
longjmp 返回值 r = 0 <==> 初始执行 返回值 为 0;
进入f1()
F1 正确执行
退出f1()
进入f2()
F2 执行错误 <==> longjmp 跳转;
longjmp 返回值 r = 2 <==> 重新返回 setjmp 处,其r值即为longjmp的第二参数;
else if 2 返回值 r = 2 <==> 执行 else if 语句
处理错误2
欣赏此文? 求鼓励,求支持!