C++中的错误处理机制
异常的引出
如过你写过不少的程序的话,相信你应该遇到过一些程序所不能处理的错误而导致程序崩溃的问题吧,比如说:操作野指针,访问空指针,函数的除零错误,数组越界,在栈上开辟空间过大导致栈溢出等等……对于我们人来说,犯错并不可怕,可怕的是不改正错误,对于程序来说也是如此。程序执行的时候,难免会发生这样或者那样的错误,要想改正错误,所使用的编程语言得提供处理错误的机制;
学习过C语言的人都知道,C语言中的错误处理的方式有 终止程序 和 返回错误码;这两种方式确实可以处理程序中的大量错误,但是C语言的这两种处理错误的方式都有点不足;
- 比如说 终止程序这种方式,当程序中发生错误的时候,直接就终止整个程序,但是我们希望我们的程序在发生错误的语句之后还要执行,比如说我们还需要释放内存空间,直接终止程序导致内存空间没有释放,造成内存泄漏的问题,如果这是一个服务器程序,就会导致服务器资源紧缺,服务器运行越来越慢,具有卡死的风险。
- 再或者说返回错误码这种方式,程序员需要自己根据返回的错误码去 错误码表中找对应的错误 ,如果返回的错误码比较多,查找起来是一件很难受的事情。说白了就是,返回错误码的方式不直接,程序员不能直接清楚的知道对应的错误是什么。
基于C语言中对错误处理的种种不便,C++语言呢 完善了对错误的处理机制(C++语言本来就是基于C语言所产生的,C++语言要兼容C语言的绝大部分语法),这种新的处理错误的机制就是异常。
如何使用C++中的异常机制
C++中要想使用异常来处理错误,需要通过 try、catch、throw 三个关键字来进行
- try 具有尝试的意思,后面跟一个代码块,意思是尝试一下代码块中的代码,如果该代码块中抛出了异常,就交给类型匹配的 catch 代码块处理。如果没有抛出异常,就执行 catch 代码块后面的语句。
- catch 具有捕捉,抓住的意思,catch后面跟一个圆括号,圆括号后面跟一个花括号;圆括号中的内容表示捕捉的异常的类型,花括号中就可以处理该异常了;try代码块后面可以跟多个catch 代码块。(注意:捕捉的异常类型 和抛出的异常类型 是匹配的,这里的匹配有两种匹配方式 1、抛出A类型的异常,被接收A类型异常的catch语句捕获;2、抛出子类类型的异常,被接收该父类类型的catch语句捕获。)
- throw 具有扔、抛的意思,throw 后面跟抛出的异常对象。抛出的异常对象一旦被捕获,程序就跳转到捕获异常的catch代码块中执行,如果到main函数中都还不能被捕获,则终止程序。
#include <iostream>
using namespace std;int func(int &a, int &b)
{if(0 == b)throw "这是一个除零错误"; int c = a / b;return c;
}int main()
{try{int a = 1;int b = 0;func(a, b);}catch(const char* err_message){cout << err_message << endl; }catch(...) // ... 表示捕获任意类型的异常{cout << "未知异常" << endl;}return 0;
}
总的来说就是,C++中的异常是通过对象的形式抛出来的,该对象的类型决定了 匹配哪个 catch 代码块 来处理,匹配的catch代码块是 函数调用链中与该对象类型匹配 且 离抛出异常位置最近的那一个。那抛出的异常对象到底是什么呢?异常对象是一个局部对象,局部对象出了作用域就会销毁,所以抛出该局部对象的时候,会生成一个临时变量,这个临时变量会在被捕获后销毁;这里类似于函数的传址返回,可以看出右值引用的移动语义也有提高抛出异常的效率。
函数调用链中异常栈是如何展开和匹配的
异常的使用难免弯弯绕绕,所以我们要搞清楚异常是如何匹配的,说白了就是通过 throw 抛出的异常对象应该被哪个catch代码块捕获处理。
当通过 throw 抛出异常对象的时候,首先要检查 throw 本身是否在 try 代码块内部,如果在的话,再去找匹配的 catch 代码块,如果找到了匹配的 catch 代码块的话,就跳到 匹配的 catch 代码块中执行,如果没有找到匹配的 catch 代码块,就会退出当前函数栈,在上一层函数栈中继续寻找匹配的 catch 代码块。如果返回到 main 函数的函数栈中依旧没有找到对应的catch代码块,就会终止该程序。所以为了保险起见,通常会在最后加一个 catch(...) 表示捕获任意类型的异常,避免程序终止。执行完 catch 代码块中的内容之后,会继续执行 catch 代码块后面的内容。
异常的重新抛出
异常为什么需要重新抛出呢?
当一个函数捕获到它不能或不应该处理的异常时,重新抛出这个异常可以确保错误信息被传递到能够处理该异常的代码中去。这样,调用者有机会捕获并处理这个异常,或者进一步地将它传递给它的调用者。
异常如何重新抛出?
直接在捕获异常对象的 catch 代码块中使用 throw 关键字,直接上代码:
#include <iostream>
using namespace std;int func2(int &a, int &b)
{if(0 == b)throw "这是一个除零错误"; int c = a / b;return c;
}void func1()
{int a = 1;int b = 0;try{func2(a,b);}catch(...){cout << "重新抛出异常" << endl;throw; // 使用throw关键字重新抛出异常}
}int main()
{try{func1();}catch(const char* err_message){cout << err_message << endl; }return 0;
}
使用异常可能存在的问题
众所周知,程序是按照一定的执行流执行的,但总有一些操作试图打破程序的执行流,比如:continue语句,break语句,goto语句(不推荐使用),return语句;在加上我们刚刚学习的 try…catch语句 也是可以打破程序的执行流的,continue、break、return语句都是可控的,但是 try…catch语句 会直接跳转到匹配的 catch 代码块中执行,这也就意味着处于 throw 和该catch代码块之间的语句不会被执行,如果这是一些涉及资源释放的语句的话,就会造成资源没有被释放,从而导致内存泄漏的问题。如果是多线程的代码,异常的抛出导致 unlock() 未被执行,就会导致死锁问题。如何解决呢?通过智能指针解决。
由此可见,对于异常的使用需要小心小心再小心。而且在一些场景中是不能抛异常的,比如,不要在 构造函数 和 析构函数 中抛异常。
- 不要在构造函数中抛异常:构造函数是用来初始化对象的,如果在构造函数中抛异常,可能导致对象初始化不完整,影响后续的使用。
- 不要在析构函数中抛异常:析构函数是用来清理对象中的资源的,如果在析构函数中抛异常,可能导致对象中资源清理不完全,如果析构函数中需要 释放资源or解锁,就会造成内存泄漏or死锁的问题。
异常的优缺点
优点:
1.异常可以更加清晰的展示出错误的信息,可以更好的帮助我们定位程序中的bug。
-
在实际开发中,通常会自定义一套异常体系,定义一个基类,不同的模块可能会抛出的异常定义为派生类,这样,抛出的异常是哪个模块的就清晰明了了。
2.处理错误速度更快
-
异常体系中,一旦抛出异常,程序直接跳转到匹配的 catch 代码块中执行;如果是返回错误码的方式的话,需要层层返回,在最外层才能拿到错误码。
3.弥补了一些场景下处理错误的不足
- 比如:有些函数没有返回值,不方便使用错误码返回错误信息。
缺点
1.try catch语句会造成程序的执行流乱跳,导致调试和分析问题时比较困难;也有可能导致不可预料的问题(在使用异常可能会存在的问题中已经分析过了)
2.C++中的异常体系定义的不好,大家自己定义自己的异常体系,非常混乱。
3.异常要是使用不规范的话,会增加而外的使用成本。
相关文章:
C++中的错误处理机制
异常的引出 如过你写过不少的程序的话,相信你应该遇到过一些程序所不能处理的错误而导致程序崩溃的问题吧,比如说:操作野指针,访问空指针,函数的除零错误,数组越界,在栈上开辟空间过大导致栈溢…...
【杂乱笔记】图论
图论 文章目录 图论图的存储与深度、广度遍历基础定义代码实现其他补充 并查集基础定义代码实现 最小生成树基础定义代码实现**Kruskal算法**prim算法 拓扑排序基础定义思路分析代码实现 最短路径基础定义代码实现Dijkstra算法Bellman-Ford算法Floyd算法 图的存储与深度、广度遍…...

pdf文件密码忘记,有办法可以打开pdf文件吗?
为确保PDF文件的重要信息不轻易外泄,我们一般会给pdf文件设置打开密码,确保pdf文件的隐私与安全,但随着时间的推移,让我们遗忘了原本设置的密码,这时我们该怎么办呢? 当大家遇到这种情况时,可能…...
git , nvm 快速下载安装包链接
为了记录地址 , 都是复制大神的 , 可以用!!! nvm 包管理工具 和 git安装包 1. nvm https://www.jianshu.com/p/13c0b3ca7c71 https://blog.csdn.net/i_for/article/details/135060019 https://www.cnblogs.com/Fooo/p…...

TongHttpServer安装部署
TongHttpServer安装部署 毫无背景不是你堕落的理由,而更应该是你前进的动力。你该花时间思考,如何打好一副烂牌;而不是抱怨命运,或者干脆撕牌。 部署环境 TongHttpServer V6.0是一款轻量级负载均衡软件,支持 0SI 四层…...
Robot Operating System——操纵杆反馈
大纲 应用场景定义字段解释 案例 sensor_msgs::msg::JoyFeedback 是 ROS (Robot Operating System) 中的一个消息类型,用于表示操纵杆(如游戏手柄或飞行摇杆)的反馈信息。它通常用于传输和处理操纵杆的振动、LED状态等反馈信息。 应用场景 机…...
nginx相关博客
nginx变量 NGINX脚本语言原理及源码分析(一):开源Web服务提供商 - NGINX开源社区 NGINX 脚本语言原理及源码分析(二):开源Web服务提供商 - NGINX开源社区...
字符串及转义字符
字符串 在c语言中 形如‘a ’b ‘c 等单个字母被命名为字符常量 而形如“abcdef”等则被命名为字符串 在c语言中,有整形,单精度浮点数,字符数据类型 但却没有字符串类型 所以在初始化字符串时与初始化字符相同 列:char c…...

软考学习笔记(0):软考准备
文章目录 前言软考的优点软考项目的选择资料选择时间安排 前言 最近因为某些原因,我又开始上班了。新工作是纯内网开发,那以后发博客的频率我估计就会很少了。 软考的优点 简单来说,软考考上了,大概一个月的薪资可以涨1000-300…...
Leetcode 70.爬楼梯
假设你正在爬楼梯。需要 n 阶你才能到达楼顶。 每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢? 示例 1: 输入:n 2 输出:2 解释:有两种方法可以爬到楼顶。 1. 1 阶 1 阶 2. 2 阶 示例 2&#…...

Spring Boot集成钉钉群通知机器人
文章目录 一、钉钉机器人配置1)添加机器人2)添加自定义机器人3)设置机器人参数4)添加机器人完成 二、依赖导入三、工具类封装四、关键字推送消息测试类1)测试类2)程序输出结果:3)通知…...

SpringAOP 面向切面编程
** Spring有两大核心特性:IOC(控制反转) 和 AOP(面向切面编程),但是 相比IOC在日常工作中的广泛应用,AOP却常常做了冷板凳,下面我从工作中的场景为大家打开AOP面向切面编程的大门。** 什么是AOP? 在软件业,AOP为Asp…...

灵办AI助手Chrome插件全面评测:PC Web端的智能办公利器
探索灵办AI助手在Mac OS上的高效表现,支持多款主流浏览器,助你轻松应对办公挑战 文章目录 探索灵办AI助手在Mac OS上的高效表现,支持多款主流浏览器,助你轻松应对办公挑战摘要引言开发环境介绍核心功能评测1. 网页翻译与双语对照 …...

Rancher 使用 Minio 备份 Longhorn 数据卷
0. 概述 Longhorn 支持备份到 NFS 或者 S3, 而 MinIO 就是符合 S3 的对象存储服务。通过 docker 部署 minio 服务,然后在 Longhorn UI 中配置备份服务即可。 1. MinIO 部署 1.1 创建备份目录 mkdir -p /home/longhorn-backup/minio/data mkdir -p /home/longhor…...
useRequest
用法 默认用法 第一参数是异步函数(接口),在组件初次加载时,会自动触发该函数执行。 const { data, error, loading } useRequest(getUsername);第二个参数,是一个配置选项(一个对象) 详解…...

python动画:manim实现多面体的创建
一,介绍 内容 多面体(discusses polyhedra),主要集中在一种称为多面体的几何形状类别,并突出介绍了五种柏拉图体(Platonic solids),这些是具有特殊性质的多面体类型。 多面体 定义…...

数值计算引擎:搭建远程容器开发环境
Build VS Code Remote Docker Development Environment 大型CAE软件开发技术栈通常依赖多个第三方库,因此从零开始配置开发、编译、运行等环境通常较为繁琐。但随着公司的发展壮大,却经常需要为新加入的成员配备相应的开发环境;另外…...

二叉搜索树(Binary Search Tree)
1.二叉搜索树概念 二叉搜索树又称二叉排序树、二叉查找树,它或者是一棵空树,或者是具有以下性质的二叉树: 1. 非空左子树的所有键值小于其根节点的键值 2. 非空右子树的所有键值大于其根节点的键值 3. 左右子树也分别为二叉搜索树 二叉搜索树一般不支持…...
Yii2框架的初始化及执行流程
当 Yii2 框架执行 index.php 入口脚本后,内部执行逻辑和顺序可以概括如下: 1、加载相关配置文件和关键组件: 加载 Composer 自动加载器: require DIR . ‘/…/vendor/autoload.php’; 加载 Yii 框架文件: require D…...

2024.1-2024.2pycharm无法打开terminal命令行
2024版的idea或pycharm打开terminal时会发生如下问题: Cannot open Windows PowerShell Failed to start [C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe,或 Cannot open Command Prompt Failed to start [C:\Windows\system32\cmd.exe] 需要点击标…...
KubeSphere 容器平台高可用:环境搭建与可视化操作指南
Linux_k8s篇 欢迎来到Linux的世界,看笔记好好学多敲多打,每个人都是大神! 题目:KubeSphere 容器平台高可用:环境搭建与可视化操作指南 版本号: 1.0,0 作者: 老王要学习 日期: 2025.06.05 适用环境: Ubuntu22 文档说…...

基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...

Debian系统简介
目录 Debian系统介绍 Debian版本介绍 Debian软件源介绍 软件包管理工具dpkg dpkg核心指令详解 安装软件包 卸载软件包 查询软件包状态 验证软件包完整性 手动处理依赖关系 dpkg vs apt Debian系统介绍 Debian 和 Ubuntu 都是基于 Debian内核 的 Linux 发行版ÿ…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...

376. Wiggle Subsequence
376. Wiggle Subsequence 代码 class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();int res 1;int prediff 0;int curdiff 0;for(int i 0;i < n-1;i){curdiff nums[i1] - nums[i];if( (prediff > 0 && curdif…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信
文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...