异常处理

程序消亡的一般形式:无疾而终、自杀、他杀、

C异常处理

传统错误处理方式:
1.终止程序(除数为0)
2.返回一个表示错误的值,附加错误码(GetLastError())
3.返回一个合法值,让程序处于某种非法的状态(坑爹的atoi())
4.调用一个预先准备好在出现”错误”的情况下用的函数(回调函数)。
5.暴力解决方式:abort()或者exit()
6.使用goto语句
7.setjmp()和longjmp()组合
【注意】
1、setjump必须先调用,在异常位置通过调用longjmp以恢复先前被保存的程序执行点,否则将导致
不可预测的结果,甚至程序崩溃。
2、在调用setjmp的函数返回之前调动longjmp,否则结果不可预料。
setjmp()和longjmp()存在以下缺陷:
1、函数的使用者必须非常靠近函数调用的地方编写错误处理代码,无疑使代码变的臃肿笨拙。
2、setjmp()和longjmp()并不能够很好的支持C++面向对象的语义。

C++异常处理
异常,当一个函数发现自己无法处理的错误时抛出异常,让函数的调用者直接或间接的处理这个问
题。
异常的抛出和捕获
1. 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个处理代码。
2. 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
3. 抛出异常后会释放局部存储对象,所以被抛出的对象也就还给系统了,throw表达式会初始化一个
抛出特殊的异常对象副本(匿名对象),异常对象由编译管理,异常对象在传给对应的catch处理之
后撤销。
栈展开
抛出异常的时候,将暂停当前函数的执行,开始查找对应的匹配catch子句。
首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。
如果有匹配的,则处理。没有则退出当前函数栈,继续在调用函数的栈中进行查找。
不断重复上述过程。若到达main函数的栈,依旧没有匹配的,则终止程序。
上述这个沿着调用链查找匹配的catch子句的过程称为栈展开。
找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
异常捕获的匹配规则
异常对象的类型与catch说明符的类型必须完全匹配。只有以下几种情况例外
1. 允许从非const对象到const的转换。
2. 允许从派生类型到基类类型的转换。
3. 将数组转换为指向数组类型的指针,将函数转换为指向函数类型的指针。
异常的重新抛出
有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用链
函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

异常与构造函数&析构函数
1. 构造函数完成对象的构造和初始化,需要保证不要在构造函数中抛出异常,否则可能导致对象不
完整或没有完全初始化。
2. 析构函数主要完成资源的清理,需要保证不要在析构函数内抛出异常,否则可能导致资源泄漏
(内存泄漏、句柄未关闭等)

C++标准库定义的exception类&自定义异常类

exception类是C++定义的一个标准异常的类,通常我们通过继承exception类定义合适的异常类。

异常的优缺点:
优点:
1.比返回错误码的传统方式更清晰地表示程序错误;
2.很多C++的第三方库使用异常,使用异常能更好的用这些库;
3.引入异常能更好地测试代码,因此如测试框架使用异常。
缺点:
1.执行乱跳,不方便调试跟踪代码 ;
2.异常安全的问题,需要更好使用RAII编写异常安全的代码,如智能指针。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值