linux程序 报浮点异常,linux c语言编程,使用setjmp和longjmp函数自制类似python的try-catch模块捕获异常,处理段错误,浮点错误等信号错误(1)...

程序的非逻辑错误

程序出错大体可以分两种,一种是出错时,程序不会退出,可以继续往下执行,例如 open 文件失败,也只是无法打开文件而已,程序还可以执行我们设定的错误处理语句,比如打印出错误信息等。还有一种错误发生时,程序直接就退出了,例如非法操作指针引起的段错误,把 0 做被除数的浮点错误等。

e3ac49da58078bd3ebad1c4525141147.png

先来看一段 c 代码,代码很简单,就是计算 8 除以 0 的值,传递给 a。显然,任何数除以 0 都是无法计算的,所以编译的时候,编译器会发出警告:

出现警告,我们当然可以立刻修改代码。可是,有时候 0做被除数不是显式的,此时编译器就发现不了这种错误了,当然不会再给出警告,例如下面这段代码:

编译之,发现没有警告,执行时却报错了,程序直接退出了。如下:

python 处理错误的 try 语句

再来看看使用 python 代码重写的代码,同样计算 8 除以 0 的值,传递给 a。

我们执行之,发现错误被 try 语句捕获了,打印信息如下:

错误发生后,程序没有直接退出,执行了我们安排的错误打印语句,这就让程序的稳定性更加强了。

c079e841b51cef62adc26e5c04c11047.png

C 语言实现逻辑跳转

c 语言没有直接提供类似 python 的 try 功能,但是提供了 setjmp 和 longjmp 函数用于保存现场和恢复现场。先简单介绍下这两个函数:

所需头文件

setjmp 和 longjmp 函数原型

setjmp 和 longjmp 函数在处理底层错误时非常有用。longjmp函数可以恢复setjmp保存的现场,简单来说就是使用 longjmp 函数可以跳转到setjmp函数处。setjmp函数首次成功执行时返回 0,通过longjmp函数返回到setjmp后,setjmp返回值等于longjmp的参数二val。

请看下面这段代码:

编译之,执行得如下结果:

首次到达 setjmp 函数时,ret 等于 0,因此打印了“ret == 0 is true”,紧接着longjmp函数得以执行,程序又返回到setjmp,只不过这次 ret 等于 longjmp 函数的第二个参数,即 ret 等于 -1,接着,"ret == 0 is false"就被打印出来了。

C 语言实现类似 python 的 try 功能

可以看出,setjmp 和 longjmp 函数使用好了,可以实现代码的任意跳转,如果再加上信号处理函数,则完全可以实现类似 python 的 try 功能。请看下面这段代码:

我们知道,在 linux 系统中,如果出现 0 做被除数的错误,则会收到 SIGFPE 信号,我们这里指定处理该信号的函数为 sigHandle 函数,这样就可以在出现错误时,重新跳转回 sigsetjmp 函数,根据返回值的不同,就可以执行错误打印函数了。带sig前缀的setjmp和longjmp函数,可以保存信号。如果sigsetjmp函数的第二个参数不是 0,那么程序的 signal mark 将会被保存下来。

编译上面的代码,执行结果如下:

程序执行到 a = 8/0; 语句时,出现浮点错误,程序进入 sigHandle 函数,跳回sigsetjmp函数,返回值变为 -1,此时“ERROR: division by zero”就被打印出来了。这样,我们的 C 语言也有类似于 python 的 try 功能了。

上述代码的缺点和为解决的问题

上面一节的代码,虽然成功模拟了 python 的 try 功能,但是有两个致命问题:覆盖了原有的信号处理函数。

信号处理函数不能传递参数,因此只能使用全局变量,但是这样一来,模拟 try 功能就不能支持嵌套使用了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值