异常概念
程序在运行过程中可能产生异常,异常是程序运行时可预料的执行分支,Bug是程序错误,是不可被预期的运行方式
C语言处理异常的方式
void func(...)
{
if(判断是否产生异常)
{
正常情况代码逻辑;
}
else
{
异常情况代码逻辑;
}
}
例子:
#include <iostream>
#include <string>
using namespace std;
double divide(double a, double b, int* valid)
{
const double delta = 0.000000000000001;
double ret = 0;
if( !((-delta < b) && (b < delta)) )
{
ret = a / b;
*valid = 1;
}
else
{
*valid = 0;
}
return ret;
}
int main(int argc, char *argv[])
{
int valid = 0;
double r = divide(1, 0, &valid);
if( valid )
{
cout << "r = " << r << endl;
}
else
{
cout << "Divided by zero..." << endl;
}
return 0;
}
这个代码在功能上满足了处理异常的要求,但是做除法操作要用到3个参数
一点都不优雅,divide函数调用后必须判断valid的结果来看是否出现异常,降
低代码的可读性**,我们可以通过setjmp()和longjmp()进行优化**,在使用这
两个函数必须谨慎执行
例子:
#include <iostream>
#include <string>
#include <csetjmp>
using namespace std;
static jmp_buf env;
double divide(double a, double b)
{
const double delta = 0.000000000000001;
double ret = 0;
if( !((-delta < b) && (b < delta)) )
{
ret = a / b;
}
else
{
longjmp(env, 1);
}
return ret;
}
int main(int argc, char *argv[])
{
if( setjmp(env) == 0 )
{
double r = divide(1, 1);
cout << "r = " << r << endl;
}
else
{
cout << "Divided by zero..." << endl;
}
return 0;
}
结果:
"Divided by zero..."
最开始的时候程序从main开始运行,运行到" setjmp(env) == 0 "这个语句时,调用了setjmp把当前上下文保存在env全局变量里面,因为我们是直接调用,保存完了返回值为0,即调用了divide函数,当b为
0时就走到longjump分支,longjump就根据env恢复之前保存的程序上下文,并且返回值为1,回到原来的上下文出口和0比较不成立则输出异常语句,这个程序虽然优雅,但是破坏了结构化设计的三大特性
和涉及到使用全局变量,所以C语言异常处理还是if…else…结构,C++中引入了更好的异常机制
C++语言处理异常的方式
C++内置了异常处理的语法元素try…catch…
try语句处理正常代码逻辑
catch语句处理异常情况
try语句中抛出的异常由对应的catch语句处理
try
{
double r = divide(1,0);
}
catch(...)
{
cout<<"Divided by zero..."<<endl;
}
C++异常处理分析
-throw抛出的异常必须被catch处理
当前函数能够处理异常,程序继续往下执行
当前函数无法处理异常,则函数停止执行,并返回