63、C语言异常处理

1、异常处理

  • 异常和 Bug 的区别

异常:程序运行时可预见的问题。(比如:两个数相除,我们要考虑到被除数为 0 程序会有异常)
例子:运行时产生除0的情况;需要打开的外部文件不存在;数组访问越界

Bug:程序中的错误,是不被预期的运行方式
例子:使用野指针;堆数组使用结束后未释放;选择排序无法处理长度为 0 的数组

  • C语言经典处理方式:if…else…
void func()
{
	if(判断是否产生异常)
	{
		//正常代码逻辑;
	}
	else
	{
		//异常代码逻辑;
	}
}

很多时候我们写的程序无法区分到底哪里的结果是异常,程序如下:

#include <iostream>
#include <string>

using namespace std;
double divide(double a, double b)
{
	double delta = 0.00000001;
	double ret = 0;
	if (!((-delta < b) && (b < delta)))
	{
		ret = a / b;
	}
	else
	{
		ret = 0;
	}
	return ret;
}

int main()
{
	cout << divide(1, 1) << endl;
	cout << divide(1, 0) << endl;
	cout << divide(0, 1) << endl;
	return 0;
}

在这里插入图片描述
在这个程序里,你能根据最后的输出结果判断哪个运行结果出现异常吗?肯定不能,所以这个程序缺少异常检查措施。
优化措施:

#include <iostream>
#include <string>

using namespace std;
double divide(double a, double b,int* value)
{
	double delta = 0.00000001;
	double ret = 0;
	if (!((-delta < b) && (b < delta)))
	{
		ret = a / b;
		*value = 1;
	}
	else
	{
		*value = 0;
	}
	return ret;
}

int main()
{
	int value = 0;
	double r = divide(1, 0, &value);
	if (value)
	{
		cout << "r = " << r << endl;
	}
	else
	{
		cout << "divide by zero..." << endl;
	}

	return 0;
}

在这里插入图片描述
分析:这个程序我们确实实现了异常处理的情况,但是,参数相比较一般的+、-、*、/ 运算多了一个,这就是它的缺陷。

2、异常处理的方式

  • 通过 setjmp()longjmp() 进行优化
    int setjmp(jmp_buf env) (将当前上下文保存在 jmp_buf 结构体中)
    void longjmp(jmp_buf env, int val)(从jmp_buf 结构体中恢复setjmp()保存的上下文,最终从setjmp()函数调用点返回,返回值为val)
#include <iostream>
#include <string>
#include <csetjmp>
using namespace std;
static jmp_buf env;
double divide(double a, double b)
{
	double delta = 0.00000001;
	double ret = 0;
	if (!((-delta < b) && (b < delta)))
	{
		ret = a / b;
		
	}
	else
	{
		longjmp(env, 1);
	}
	return ret;
}

int main()
{
	if (setjmp(env) == 0)
	{
		double r = divide(1, 0);
		cout << "r = " << r << endl;
	}
	else
	{
		cout << "divide by zero..." << endl;
	}
	return 0;
}

在这里插入图片描述
这个程序是这个意思,全局数据区定义了env = 0;在主函数先通过if (setjmp(env) == 0)判断出为0,进入下面程序运行 devide()函数时,当有异常情况出现,通过它longjmp(env,1);把 env 置为 1并且直接跳转到24行代码这里进行再判断。从而转向了异常输出程序。这种方法逻辑很绕,并且破坏了程序的顺序性。

缺陷: setjmp()longjmp() 的引入

  • 必然涉及到使用全局变量
  • 暴力跳转导致代码可读性降低
  • 本质还是if…else…异常处理方式

C语言容易把正常处理程序的代码和异常处理程序的代码搅在一起,使得程序看起来纷繁复杂,一眼看过去你都不知道到底哪个是正确运行的代码。

小结:
— 程序中不可避免的会发生异常
— 异常是在开发阶段就可以预见的运行时的问题
— C语言中同归经典的if…else…方式处理异常
— C++中存在更好的异常处理方式

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值