linux c语言编程,使用setjmp和longjmp函数自制类似python的try-catch模块捕获异常,处理段错误,浮点错误等信号错误(1)
发表于: 2018-10-21 21:31:58 | 已被阅读: 25 | 分类于: C语言
程序的非逻辑错误
程序出错大体可以分两种,一种是出错时,程序不会退出,可以继续往下执行,例如
先来看一段 c 代码,代码很简单,就是计算 8 除以 0 的值,传递给 a。显然,任何数除以 0 都是无法计算的,所以编译的时候,编译器会发出警告:
#include <stdio.h>
int main()
{
int a = 8/0;
return 0;
}
$ gcc t.c
t.c: In function ‘main’:
t.c:5:14: warning: division by zero [-Wdiv-by-zero]
int a = 8/0;
^
出现警告,我们当然可以立刻修改代码。可是,有时候
#include <stdio.h>
int main()
{
int b = 1;
int c = 1;
int a = 8/(b-c);
return 0;
}
编译之,发现没有警告,执行时却报错了,程序直接退出了。如下:
$ gcc t.c
$ ./a.out
Floating point exception (core dumped)
python 处理错误的 try 语句
再来看看使用
#encoding=utf8
if __name__=="__main__":
try:
a = 8/0
except Exception, e:
print 'ERROR: ', e
我们执行之,发现错误被
$ python t.py
ERROR integer division or modulo by zero
错误发生后,程序没有直接退出,执行了我们安排的错误打印语句,这就让程序的稳定性更加强了。
C 语言实现逻辑跳转
c 语言没有直接提供类似 python 的 try 功能,但是提供了
所需头文件
#include <setjmp.h>
setjmp 和 longjmp 函数原型
int setjmp(jmp_buf env);
void longjmp(jmp_buf env, int val);
请看下面这段代码:
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
int main()
{
jmp_buf mark;
int ret = 0;
ret = setjmp(mark);
if(0==ret){
printf("ret == 0 is true\n");
longjmp(mark, -1);
}else{
printf("ret == 0 is false\n");
}
return 0;
}
编译之,执行得如下结果:
$ ./a.out
ret == 0 is true
ret == 0 is false
首次到达
C 语言实现类似 python 的 try 功能
可以看出,
#include <stdio.h>
#include <setjmp.h>
#include <signal.h>
jmp_buf mark;
void sigHandle(int sig)
{
siglongjmp(mark, -1);
}
int main()
{
int ret = 0, a = 0;
signal(SIGFPE, sigHandle);
ret = sigsetjmp(mark, 1);
if(0==ret){
a = 8/0;
printf("ret == 0 is true\n");
}else{
printf("ERROR: division by zero\n");
}
return 0;
}
我们知道,在 linux 系统中,如果出现 0 做被除数的错误,则会收到 SIGFPE 信号,我们这里指定处理该信号的函数为
编译上面的代码,执行结果如下:
$ ./a.out
ERROR: division by zero
程序执行到 a = 8/0; 语句时,出现浮点错误,程序进入
上述代码的缺点和为解决的问题
上面一节的代码,虽然成功模拟了 python 的 try 功能,但是有两个致命问题:
- 覆盖了原有的信号处理函数。
- 信号处理函数不能传递参数,因此只能使用全局变量,但是这样一来,模拟 try 功能就不能支持嵌套使用了。
下一节,将解决这两个问题。
下一节:linux c语言编程,使用setjmp和longjmp函数自制类似python的try-catch模块捕获异常,建立栈数据结构,实现多级嵌套使用(2)