c++ assert和异常

参考西北工业大学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捕获,只能传到上一级函数。

猜你喜欢

转载自blog.csdn.net/qq_58550520/article/details/128900624