参考西北工业大学mooc视频
1、assert定义与使用
assert的使用需要包含头文件<cassert>我们写一个简单的c++程序,如下:
#include <iostream>
#include <cassert>
int main()
{
int i = 20;
assert(i == 65);
return 0;
}
gcc可以正常编译通过,但是执行的时候就会出现以下的报错:
assert: assert.cpp:7: int main(): Assertion `i == 65' failed.
Aborted (core dumped)
通过上面的demo测试,我们可以利用assert在某个程序里的关键假设不成立时立即停止该程序的执行并报错,从而避免更严重的问题。
我们看另外一个小demo
#include <iostream>
#include <cassert>
int main()
{
int i = 20;
int div = 0;
assert(div != 0 && "divisor cannot be zero!");
int a = i/div;
return 0;
}
gcc同样可以正常编译通过,执行时会出现以下错误
assert: assert.cpp:8: int main(): Assertion `div != 0 && "divisor cannot be zero!"' failed.
Aborted (core dumped)
除数等于0肯定会出现问题的,我们在执行到int a = i/div;代码之前加上一个assert来进行限制div的范围,通过&&同时打印出出错的debug信息。
2、停用assert
#define NDEBUG // 必须写在头文件之前
assert只针对于DEBUG版本,user版本需要将assert去掉。使用上述宏意味着assert不再提供功能,且里面的函数调用也不会运行。
3、异常处理的定义
在设计各种软件系统中,处理程序中的错误和其它反常行为是非常困难的,比如服务器上长期运行的网络服务程序将80%的代码用于实现错误检测和错误处理。
异常是指程序运行时出现的不正常。程序运行过程中可能会出现下列异常:
1)cpu异常,出现上面1中除数为0的情况
2)内存异常;
new申请内存但存储空间不够
数组下标越界
使用野指针读取内存
3)设备异常
无法打开文件
4)用户数据异常
scanf输入时数据格式或类型有错误
c++异常处理机制:抛出异常throw,检查异常try、捕获异常catch。
基本原理:把需要检测的程序放到try块中,把异常处理的程序放到catch中。如果执行一个函数时出现异常,可以不在该函数中立即处理,而是抛出异常信息,传递给它的上一级函数(调用函数),它的上一级函数捕获到这个信息后再进行处理。如果上一级函数也不处理,就逐级向上处理。如果传递到最高一级(如main函数)还不处理,最后只能异常终止程序的执行。
c++异常处理机制使异常与处理可以不由同一个函数来完成。
4、异常处理的实现
1)抛出异常
可以使用throw表达式抛出异常,将异常抛给主调函数去处理。
throw表达式的一般形式为:
throw 表达式;
异常通常以类似于实参传递给参数的方式抛出和捕获,throw表达式的类型决定了所抛出的异常类型。
在抛出异常时,throw表达式的值没有实际意义,而表达式的类型则是非常重要的。如果程序中有多处要抛出异常,应该用不同的表达式类型来相互区别。
关于throw的说明:
(1)执行throw时候,不会执行跟在throw后面的语句,而是将程序从throw转移到匹配的catch,该catch可以是同一函数中的catch,也可以在直接或者间接调用发生异常函数的上一级函数中。
(2)被抛出的对象是一个用throw表达式初始化的“异常对象”。异常对象由throw创建,并初始化为被抛出的表达式副本。
(3)如果抛出的是数组,被抛出的对象自动转换为指向该数组首元素的指针,如果抛出的是一个函数,函数被转换为指向该函数的指针。
(4)如果抛出一个指针,该指针是一个指向派生类对象的基类指针,则那个对象将被分割,只抛出基类的部分。
具体使用:
一个try块可以紧跟多个catch块。在try中执行程序块所抛出的异常,通常会被其中的一个catch子句处理,一旦catch子句执行结束,程序流程继续执行紧随最后一个catch子句后面的语句。
catch子句中的异常说明符是有一个形参的参数列表:
因为不可能知道可能被抛出的所有异常,这时使用catch是非常有效的。如果catch与其他catch子句结合使用,那么它必须是最后一个,否则任何跟在它后面的catch子句都得不到匹配检测。
举例:
运行结果如下:
2)重抛异常
在catch子句中,可以再次抛出异常,例如:
其中throw不加表达式,表示再次抛出try块检测到的异常表达式(throw "hello")。
重抛异常不能被try-catch捕获,只能传到上一级函数。