当前位置: 首页 > news >正文

【C++】特别的程序错误处理方式——异常机制

在这里插入图片描述
各位大佬好,我是落羽!一个坚持不断学习进步的学生。
如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步!

也欢迎关注我的blog主页: 落羽的落羽

文章目录

  • 一、异常的概念
  • 二、异常的抛出与捕获
    • 1. 异常抛出与捕获机制
    • 2. 栈展开
    • 3. 查找匹配的处理代码
    • 4. 异常重新抛出
    • 5. 异常的安全问题

一、异常的概念

异常处理机制允许程序中独立开发的部分能够在运行时就出现的问题进行通信并做出相应的处理,异常使得我们能够将问题的检测与解决问题的过程分开,程序的一部分负责检测问题的出现,然后解决问题的任务传递给程序的另⼀部分,检测环节无须知道问题的处理模块的所有细节。

C语言中,主要通过错误码的形式处理错误,错误码本质就是对错误信息进行分类编号,拿到错误码以后还要去查询错误信息,比较麻烦。异常时抛出一个对象,这个对象可以函数更全面的各种信息。

二、异常的抛出与捕获

1. 异常抛出与捕获机制

程序出现问题时,我们通过抛出(throw)一个对象来引发一个异常,该对象的类型以及当前的函数调用链决定了应该由哪个捕获(catch)的处理代码来处理该异常。throw抛出异常后,throw后面的语句将不再执行,要在当前这个函数调用链中寻找类型匹配的catch异常捕获模块,catch可能是同一函数内的一个局部catch,也可以是调用链中另一个函数的catch,主函数中还找不到就会终止程序。如果有多个catch匹配,使用离抛出异常位置最近的那一个。代码就从找到的catch处继续执行。

根据抛出异常对象的类型不同,我们可以人为控制catch内处理异常的方式,比如打印错误信息、修改数据等等方式。而不会使程序结束。
下面这段代码举例,一个除法函数,如果被除数为0则抛出异常,异常对象是一个含错误信息的字符串。下面有一个能捕获string类的catch语句,如果抛出了这个string就能捕获到,然后打印出这个错误信息提醒用户。在这个过程中程序是正常运行的,如果是C语言的错误码处理方式,这种情形下就会导致程序直接中断。

double Div(int a, int b)
{try{if (b == 0){string s("被除数为0,错误!");throw s;}else{return (double)a / (double)b;}}catch (string& s){cout << s << endl;}return 0;
}

在这里插入图片描述

还需要注意:

  • 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象。这个拷贝对象会在catch语句后销毁。
  • 一旦程序开始执行异常处理,沿着函数调用链的创建的对象都将被销毁。

2. 栈展开

刚才说了,抛出异常后,程序将暂停当前函数的执行,开始寻找匹配的catch语句。首先检查throw本身是否在try语句内部,如果在则查找匹配的catch语句,如果有匹配的就跳到catch处执行。
如果当前函数中没有try/catch语句或catch不匹配,则退出当前函数,销毁当前函数栈帧,继续在外层函数调用链中查找,这个查找catch的过程称为栈展开。
如果到达主函数,依旧没有找到匹配的catch,程序就会调用标准库的terminate函数终止程序。

在这里插入图片描述
在这里插入图片描述

3. 查找匹配的处理代码

一般情况下抛出对象类型和catch是能完全匹配的。但是还有一些特殊情况,允许从非常量向常量的类型转换(非const转换为const)、函数被转换为函数指针、派生类转换为基类。派生类转换为基类是最实用的,实际项目中很多都是这样设计的。
main函数中还没有匹配到catch的话会终止程序,一般情况下我们都是不希望程序终止的,所以一般main函数中最后会写一个catch{...},这个catch可以捕获任意类型的异常,但是不知道异常对象是什么。有时候我们使用软件会显示“未知异常”,可能就是执行了这个catch语句。

4. 异常重新抛出

有时catch到一个异常对象时,需要对错误进行分类,比如某种错误类型需要进行特殊处理再抛出,只需要在处理完成后再写一个throw;,就完成了异常的再次抛出

5. 异常的安全问题

异常抛出后,后面的代码就不再执行,前面申请了的资源(内存、锁等),后面需要进行释放,但是中间可能会抛异常,就会导致资源没有释放,引发了资源泄漏,产生安全性的问题。中间我们需要捕获异常,释放资源后面再重新抛出,十分麻烦。下一篇文章我们学习智能指针,就可以解决这个问题。

其次析构函数中,如果抛出异常也要谨慎处理,比如析构函数要释放10个资源,释放到第5个时抛出异常,则也需要捕获处理,否则后面的5个资源就没释放,也资源泄漏了。

除此之外,C++11中新增了一个关键字noexcept,函数参数列表后面写上noexcept表示这个函数不会抛出异常,不写就表示可能会抛出异常。
这就是为什么C++11后STL的一些容器接口写了noexcept,这种接口一定不会抛异常,如begin()、end()、size();有的接口就可能抛异常,如push、insert等。
在这里插入图片描述
在这里插入图片描述

noexcept(表达式)还可以作为运算符检测一个表达式会不会抛出异常,可能则返回false,不会抛异常就返回true。


文章转载自:

http://VwvgvvCX.srzhm.cn
http://iyGfm3r2.srzhm.cn
http://8c3F7vh1.srzhm.cn
http://JFm0Wwzc.srzhm.cn
http://NRuhHv4w.srzhm.cn
http://nQCvvhJL.srzhm.cn
http://GQ6wIHrY.srzhm.cn
http://Et0Yyvgq.srzhm.cn
http://Cz1DkBSf.srzhm.cn
http://Tc90NxkV.srzhm.cn
http://oXFr9D7D.srzhm.cn
http://4JVT0U8O.srzhm.cn
http://BQRj66wP.srzhm.cn
http://iioEqTdT.srzhm.cn
http://CTJ4SIK7.srzhm.cn
http://VKvxEOzr.srzhm.cn
http://PsznQQ0Z.srzhm.cn
http://jnIk23my.srzhm.cn
http://k6oMPnhE.srzhm.cn
http://k0f0K59V.srzhm.cn
http://NnAi4MD6.srzhm.cn
http://O3tHjm3p.srzhm.cn
http://5EK4OoTY.srzhm.cn
http://u4kPwTuk.srzhm.cn
http://JdkaEXAk.srzhm.cn
http://cOejHoAm.srzhm.cn
http://GX6L2axX.srzhm.cn
http://UHJ1U2Pe.srzhm.cn
http://CW4e0ykC.srzhm.cn
http://0Pi6ianN.srzhm.cn
http://www.dtcms.com/a/374793.html

相关文章:

  • 嵌入式设备上mqtt库的使用
  • 【Linux基础知识系列:第一百二十六篇】使用dd命令进行磁盘复制
  • 从零到一使用Linux+Nginx+MySQL+PHP搭建的Web网站服务器架构环境——LNMP(上)
  • 使用虚拟机Ubuntu搭建mosquito服务器 使esp32、上位机通信
  • 云计算技术栈
  • 国产时序数据库选型指南-从大数据视角看透的价值
  • 东京本社招聘 | 财务负责人 多个日本IT岗位(Java/C++/Python/AWS 等),IT营业同步招募
  • AWS ALB 详解:智能流量调度器
  • Django REST框架:ModelViewSet全面解析
  • 基于Centos7.9搭建svn服务端
  • PyTorch 和nn.Conv2d详解
  • pytorch基本运算-分离计算
  • 基于容器化云原生的 MySQL 及中间件高可用自动化集群项目
  • “图观”端渲染场景编辑器
  • 构建分布式京东商品数据采集系统:基于 API 的微服务实现方案
  • HTML5点击转圈圈 | 深入了解HTML5技术中的动态效果与用户交互设计
  • springboot rabbitmq 延时队列消息确认收货订单已完成
  • CString(MFC/ATL 框架)和 QString(Qt 框架)
  • Sklearn(机器学习)实战:鸢尾花数据集处理技巧
  • 工具框架:Scikit-learn、Pandas、NumPy预测鸢尾花的种类
  • AI GEO 优化能否快速提升网站在搜索引擎的排名?​
  • nvm和nrm的详细安装配置,从卸载nodejs到安装NVM管理nodejs版本,以及安装nrm管理npm版本
  • 对口型视频怎么制作?从脚本到成片的全流程解析
  • 从“能说话”到“会做事”:AI Agent如何重构日常工作流?
  • 洛谷 P1249 最大乘积-普及/提高-
  • 小红书获取笔记详情API接口会返回哪些数据?
  • JAVA Spring Boot maven导入使用本地SDK(jar包)
  • Linux/UNIX系统编程手册笔记:SOCKET
  • F5和Nginx的区别
  • 9.9网编简单TCP,UDP的实现day2