一、C异常处理:用于多层返回的setjmp/longjmp机制
C中的异常处理是通过setjmp.h头文件中定义的宏setjmp和宏longjmp实现的。
类似于退栈,setjmp/longjmp机制的使用方法:
- 在希望进行错误处理的位置用setjmp宏进行标注 把当前的“环境”(函数堆栈和寄存器)以数组方式存储
- 在可能出现错误的地方使用longjmp宏进行控制转移 恢复保存的“环境”并将执行位置转回setjmp语句的下一句
典型方法:
#include <iostream> #include <csetjmp> #include <cstdlib> using namespce std; static jmp_buf env; //jmp_buf类型的对象用于保存“环境” void f( int ); int main() { /*setjmp()第一次被调用时返回0,若是longjmp()导致的控制返回,ret会被重置为longjmp()的第二个参数。 int ret = setjmp( env); if(1 == ret) { cout<<"这里是异常处理"<<endl; exit(0); } f(0); return 0; } void f(int j) { for(;j<6;j++) { if(3==j) longjmp(env,1); } }
二、C++异常处理:try--catch--throw
虽然C++中也可以使用C的方法,但是这样做会出很多问题,例如会跳过类析构函数的调用,并且setjmp()的开销较大(保存的信息)
其实通过字面意思就差不多可以理解用法了:
- 将要检查的语句放在try{}中
- 在try{}模块中加入throw,即要抛出的异常
- 在try{}模块后加上catch{}模块捕捉异常
典型方法:
#include <iostream> #include <cstdlib> using namespce std; class MyException{}; void f(int)throw(MyException); // throw(MyException)是可选的;(比之于java),如果throw(),则表示不抛出任何异常 int main() { try{ f(0); } catch(MyException &e){ // 参数列表里可以只有类型,不包括对象(比之于java) cout<<"捕捉到异常"; } return 0; } void f(int j)throw(MyException) { throw MyException(); }
补充:
(1)try和catch块中必须要用花括号括起来,即使花括号内只有一个语句也不能省略花括号;
(2)try和catch必须成对出现,一个try_catch结果中只能有一个try块,但可以有多个catch块,以便与不同的异常信息匹配;
(3)如果在catch块中没有指定异常信息的类型,而用删节号"...",则表示它可以捕获任何类型的异常信息;
(4)如果throw不包括任何表达式,表示它把当前正在处理的异常信息再次抛出,传给其上一层的catch来处理;
(5)C++中一旦抛出一个异常,如果程序没有任何的捕获,那么系统将会自动调用一个系统函数terminate,由它调用abort终止程序;
三、java异常处理:try--catch--throw--finally
与C++的异常处理语法相似,java的异常处理在“字面”上看,只比C++多了个finally,但是细节上还是有许多不同
用法:
典型方法:
- try{}模块 放入要检查的语句
- 放入throw语句 要抛出的异常
- catch{}模块 捕捉异常
- finally{}模块 无论是否抛出异常,都要执行这一模块,无论如何,最后都要执行finally模块
class MyException extends Exception{}class Test{
static void f() throws MyException{} //注意此处throws MyException 为必须的(比之于C++),且,java用的throws,而C++是throw
public static void main( String[] args {
try{
f();
}
catch(MyException e){ //catch必须显式的指出参数对象
system.out.println("捕捉到异常");
}
finally{
system.out.println("这里是finally模块");
}
}
}
补充:
java中还有unchecked异常机制,异常的类型为RuntimeException或Error的子类,此类异常可以不必在try--catch代码块中抛出,可以直接抛出,且,其被系统捕获导致程序终止
四、一些额外的c++与java的比较
- C++可以抛出所有类型的对象,而java只能抛出Throwable的子类
- java中若要抛出异常必须在函数头部声明,而C++中只是推荐采用此方式
- java在catch模块中必须显式的制定一个异常参数对象,而C++不是必须的
五、C与C++的堆栈解退比较
假设都是在main函数中递归调用函数f(int),f(3)会导致异常
此为C:
此为C++: