学习C++的时候就没有怎么重视异常这部分知识,后来知道也基本没有看到C++项目里面用try/catch的。google编程规范中甚至直接说明不使用C++这个特性,所以我一直都没搞明白这个“简单的”try/catch。
查阅《C++编程思想》,我记录以下一些内容。首先是C语言的一些错误处理方法。
1) 出错信息可通过函数的返回值获得。如果函数返回值不能用,则可设置一全局错误判断标志(标准 C语言中 errno( )和perror( )函数支持这一方法)。由于对每个函数调用都进行错误检查,这十分繁琐并增加了程序的混乱度。程序设计者可能简单地忽略这些出错信息,因为乏味而迷乱的错误检查必须随着每个函数调用而出现。另外,来自偶然出现异常的函数的返回值可能并不反映什么问题。这中方法异常处理方法在Linux内核里面非常见,甚至可以说是标准的做法。根据函数的返回值判断函数的执行结果,再结合一大堆的goto语句,实现错误处理(比如说资源的释放)。比较常见的是资源申请的情况,如果资源数量比较多,就会出现程序逻辑复杂。goto语句很容易就把你搞得头大。2) 可使用 C标准库中一般不太熟悉的信号处理系统,利用signal()函数(判断事件发生的类型)和raise()函数(产生事件)。由于信号产生库的使用者必须理解和安装合适的信号处理系统,所以应紧密结合各信号产生库,但对于大型项目,不同库之间的信号可能会产生冲突。这种方法的缺陷更明显了,用户信号是有限的,虽然可以更换处理函数。但是冲突是几乎不可避免的,你怎么知道会不会有两个错误同时发生了,结果有一个错误信号就被忽略了。
3) 使用 C标准库中非局部的跳转函数: setjmp( ) 和 longjmp( )。 setjmp( ) 函数可在程序中存储一典型的正常状态,如果进入错误状态, longjmp( )可恢复setjmp( ) 函数的设定状态,并且状态被恢复时的存储地点与错误的发生地点紧密联系。说实话我貌似是第一次明白这东西的作用,汗!(不过现在习惯了,std::bind什么的现在也都不知道!)。下面是一个例子:其实就是抄了下书上的代码。
#include <iostream> #include <setjmp.h> using namespace std; class rainbow { public: rainbow() { cout<<"rainbow()"<<endl; } ~rainbow() { cout<<"~rainbow()"<<endl; } }; jmp_buf kansas; void OZ() { rainbow RB; for(int i=0;i<3;i++) { cout<<"there is no place like home\n"; } longjmp(kansas, 47); //这里的value是回到setjmp位置时,setjmp的返回值。如果设置为0,则返回值是1 } int main() { if(setjmp(kansas) == 0) { cout<<"tornado, witch, munchkins...\n"; OZ(); }else { cout<< "Auntie Em! " << "I had the strangest dream...\n" <<endl; } }至于C++的异常语法,其实大家都是知道的。但是它是如何实现的呢?这一直是一个疑问。后来我看了白杨的《C++异常机制的实现方式和开销分析》传送门,确实有茅塞顿开的感觉,推荐一下。
原文地址:http://blog.csdn.net/cqu20093154/article/details/44020167