C语言错误处理

        学习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++异常机制的实现方式和开销分析》传送门,确实有茅塞顿开的感觉,推荐一下。

展开阅读全文

没有更多推荐了,返回首页