大型网站建设 cms cdm dmp/谷歌play商店官网
异常的引出
如过你写过不少的程序的话,相信你应该遇到过一些程序所不能处理的错误而导致程序崩溃的问题吧,比如说:操作野指针,访问空指针,函数的除零错误,数组越界,在栈上开辟空间过大导致栈溢出等等……对于我们人来说,犯错并不可怕,可怕的是不改正错误,对于程序来说也是如此。程序执行的时候,难免会发生这样或者那样的错误,要想改正错误,所使用的编程语言得提供处理错误的机制;
学习过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] 需要点击标…...

50ETF期权移仓是什么?50ETF期权移仓要注意什么?
今天带你了解50ETF期权移仓是什么?50ETF期权移仓要注意什么?当前火热的期权交易市场,“移仓”同样是一门非常重要的技术。上证50ETF期权投资的过程中,我们可以进行一定的移仓操作的,如果移仓操作得好,可以很…...

软件工程概述(上)
1、软件的概念、特点和分类 要了解软件工程,首先让我们重新认识一下软件。如今可以说是一个软件定义一切的时代,虽然人工智能发展的如火如荼,但究其本质,核心还是软件。那么,如何给软件下一个定义呢?软件又…...

阿里云ubuntu系统安装mysql8.0
一、安装mysql8.0 1.已安装其他版本的mysql,需要删除 若没有不需要此操作 1 #卸载MySQL5.7版本 2 apt remove -y mysql-client5.7* mysql-community-server5.7* 4 # 卸载5.7的仓库信息 5 dpkg-l | grep mysql | awk iprint $2} | xargs dpkg -P2.更新仓库 apt u…...

自己搭建远程桌面服务器-RustDesk 极简版
linux搭建RustDesk保姆间教程_rustdesk linux-CSDN博客https://blog.csdn.net/yzs2022/article/details/135136491 背景 在某公司工作,向日葵等远程办公软件均已屏蔽,无法使用(也没有明文规定不允许使用远程控制软件),…...

数字资产是什么?怎么产生?怎么增长?
数字资产是什么? 数字资产是指企业或个人拥有或控制的,以电子数据形式存在的,在日常活动中持有以备出售或处于生产过程中的非货币性资产。它涵盖了广泛的范围,包括但不限于数字货币、数字证券、数字艺术品、虚拟土地等。这些资产…...

Centos7升级gitlab(17)
在 CentOS 7 中将 GitLab 从版本 17.1.1 升级到 17.2.2,涉及以下步骤。请务必在升级前备份数据,以防止升级过程中出现问题导致数据丢失。 升级步骤 1. 备份 GitLab 数据 在升级之前,确保已经备份了 GitLab 的数据,包括数据库、…...

Zookeeper详解以及常见的高可用关联组件
一、ZooKeeper 详解 Apache ZooKeeper 是一个开源的分布式协调服务,用于分布式应用程序之间的协调和管理。ZooKeeper 提供了一个高效、可靠的服务来帮助管理分布式系统中的共享配置信息、命名、同步和组服务等。 二、主要特性 1. 高可用性 ZooKeeper 集群通过选…...

Docker Containerd初体验
Docker Containerd概述 Containerd是一个开源的容器运行时,它提供了一种标准化的方式来管理容器的生命周期。该项目最初是由Docker开发团队创建的,并在后来成为了一个独立的项目,被纳入了Cloud Native Computing Foundation(C…...

开始使用 AWS SAM CLI
了解如何使用 AWS SAM CLI 在本地调试 lambda 函数 欢迎来到雲闪世界。我们将学习 AWS SAM CLI 的概念。SAM 是无服务器 应用程序 模型的缩写,是 Amazon Web Services 提供的一个框架,可以利用它在本地机器上构建应用程序并将其直接部署到 AWS Lambdas。…...

RK3588 RTL8125BG调试
RTL8125B是一款PCIE转RJ45的网卡控制器芯片,在底层调试时只需配置PCIE即可 diff --git a/arch/arm64/boot/dts/rockchip/rk3588-nvr-demo.dtsi b/arch/arm64/boot/dts/rockchip/rk3588-nvr-demo.dtsi index 798359eaf061..d8a7a43cdfa0 100755 --- a/arch/arm64/bo…...