【C++】异常( try / catch / throw)

C++ 异常 异常异常的概述了解基本方法调用abort()返回错误码异常机制四级标题五级标题六级标题三级目录值 异常的概述 程序有时会遇到运行阶段错误,导致程序无法正常的运行下去。例如:程序可能试图打开一个不可用的文件,请求过多的内存,或者遭到不能容忍的值。通常,程序员都会试图预防这种意外情况。所以c++出现了异常的功能。 了解基本方法 讨论异常之前,了解可使用的一些基本方法,例:计算两个的调和平均数的函数为例。两个数的调和平均数的定义是:这两个数字倒数的平均值的倒数。表达式:2.0xy/(x+y) 如果y是x的负值,则 阅读详情

1.C语言传统的处理错误的方式

传统的错误处理机制:

  1. 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。
  2. 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码放到errno中,表示错误。
  3. C 标准库中setjmp和longjmp组合。这个不是很常用,了解一下。

实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。

2.C++异常概念

异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者来处理这个错误。

  1. throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
  2. catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常,可以有多个catch进行捕获。
  3. try: try 块中的代码标识将被激活的特定异常,它后面通常跟着一个或多个 catch 块。

如果有一个块抛出一个异常,捕获异常的方法会使用 try 和 catch 关键字。try 块中放置可能抛出异常的代码,try 块中的代码被称为保护代码。
使用 try/catch 语句的语法如下所示:

try
{
 // 保护的标识代码
}catch( ExceptionName e1 )
{
 // catch 块
}catch( ExceptionName e2 )
{
 // catch 块
}catch( ExceptionName eN )
{
 // catch 块
}

3.异常的用法

3.1 异常的抛出和捕获

异常的抛出和匹配原则

  1. 异常是通过抛出对象而引发的,该对象的类型决定了应该激活哪个catch的处理代码。
  2. 被选中的处理代码是调用链中与该对象类型匹配且离抛出异常位置最近的那一个。
  3. 抛出异常对象后,会生成一个异常对象的拷贝,因为抛出的异常对象可能是一个临时对象,所以会生成一个拷贝对象,这个拷贝的临时对象会在被catch以后销毁。(这里的处理类似于函数的传值返回)
  4. catch(…)可以捕获任意类型的异常,问题是不知道异常错误是什么。
  5. 实际中抛出和捕获的匹配原则有个例外,并不都是类型完全匹配,可以抛出的派生类对象,使用基类捕获,这个在实际中非常实用,我们后面会详细讲解这个。

在函数调用链中异常栈展开匹配原则

  1. 首先检查throw本身是否在try块内部,如果是再查找匹配的catch语句。如果有匹配的,则调到catch的地方进行处理。
  2. 没有匹配的catch则退出当前函数栈,继续在调用函数的栈中进行查找匹配的catch。
  3. 如果到达main函数的栈,依旧没有匹配的,则终止程序。上述这个沿着调用链查找匹配的catch子句的过程称为栈展开。所以实际中我们最后都要加一个catch(…)捕获任意类型的异常,否则当有异常没捕获,程序就会直接终止。
  4. 找到匹配的catch子句并处理以后,会继续沿着catch子句后面继续执行。
    在这里插入图片描述
double Division(int a, int b)
{
 	// 当b == 0时抛出异常
 	if (b == 0)
		 throw "Division by zero condition!";
	 else
		 return ((double)a / (double)b);
}
void Func()
{
 	int len, time;
	 cin >> len >> time;
	 cout << Division(len, time) << endl;
}
int main()
{
 	try 
 	{
		 Func();
 	}
	 catch (const char* errmsg) 
	 {
		 cout << errmsg << endl;
	 }
	 catch(...)
	 {
	 	cout<<"unkown exception"<<endl;
	 }
	 return 0;
}

3.2 异常的重新抛出

有可能单个的catch不能完全处理一个异常,在进行一些校正处理以后,希望再交给更外层的调用链函数来处理,catch则可以通过重新抛出将异常传递给更上层的函数进行处理。

double Division(int a, int b)
{
 	// 当b == 0时抛出异常
 	if (b == 0)
 	{
 		throw "Division by zero condition!";
 	}
	 return (double)a / (double)b;
}
void Func()
{
 	// 这里可以看到如果发生除0错误抛出异常,另外下面的array没有得到释放。
	 // 所以这里捕获异常后并不处理异常,异常还是交给外面处理,这里捕获了再
	 // 重新抛出去。
	 int* array = new int[10];
	 try 
	 {
 		int len, time;
 		cin >> len >> time;
 		cout << Division(len, time) << endl;
	 }
 	catch (...)
	 {
		 cout << "delete []" << array << endl;
 		delete[] array;
 		throw;
 	}
 	// ...
 	cout << "delete []" << array << endl;
 	delete[] array;
}
int main()
{
	 try
 	{
		 Func();
	 }
 	catch (const char* errmsg)
 	{
		 cout << errmsg << endl;
	 }
 	return 0;
}

3.3 异常安全

  1. 构造函数完成对象的构造和初始化,最好不要在构造函数中抛出异常,否则可能导致对象不完整或没有完全初始化
  2. 析构函数主要完成资源的清理,最好不要在析构函数内抛出异常,否则可能导致资源泄漏(内存泄漏、句柄未关闭等)
  3. C++中异常经常会导致资源泄漏的问题,比如在new和delete中抛出了异常,导致内存泄漏,在lock和unlock之间抛出了异常导致死锁,C++经常使用RAII来解决以上问题,关于RAII我们智能指针这节进行讲解。
    ##3.4 异常规范
  4. 异常规格说明的目的是为了让函数使用者知道该函数可能抛出的异常有哪些。 可以在函数的后面接
    throw(类型),列出这个函数可能抛掷的所有异常类型。
  5. 函数的后面接throw(),表示函数不抛异常。
  6. 若无异常接口声明,则此函数可以抛掷任何类型的异常。
// 这里表示这个函数会抛出A/B/C/D中的某种类型的异常
void fun() throw(A,B,C,D);
// 这里表示这个函数只会抛出bad_alloc的异常
void* operator new (std::size_t size) throw (std::bad_alloc);
// 这里表示这个函数不会抛出异常
void* operator new (std::size_t size, void* ptr) throw();

4. 自定义异常体系

实际使用中很多公司都会自定义自己的异常体系进行规范的异常管理,因为一个项目中如果大家随意抛异常,那么外层的调用者基本就没办法玩了,所以实际中都会定义一套继承的规范体系。这样大家抛出的都是继承的派生类对象,捕获一个基类就可以了
在这里插入图片描述

// 服务器开发中通常使用的异常继承体系
class Exception
{
protected:
 	string _errmsg;
	 int _id;
	 //list<StackInfo> _traceStack;
	 // ...
};
class SqlException : public Exception
{};
class CacheException : public Exception
{};
class HttpServerException : public Exception
{};
int main()
{
 	try
 	{
 		// server.Start();
		 // 抛出对象都是派生类对象
	 }
	 catch (const Exception& e) // 这里捕获父类对象就可以
 	{}
	 catch (...)
	 {
		 cout << "Unkown Exception" << endl;
	 }
	 return 0;
}

5. 异常的优缺点

C++异常的优点:

  1. 异常对象定义好了,相比错误码的方式可以清晰准确的展示出错误的各种信息,甚至可以包含堆栈调用的信息,这样可以帮助更好的定位程序的bug。
  2. 返回错误码的传统方式有个很大的问题就是,在函数调用链中,深层的函数返回了错误,那么我们得层层返回错误,最外层才能拿到错误,具体看下面的详细解释。

C++异常的缺点:
4. 异常会导致程序的执行流乱跳,并且非常的混乱,并且是运行时出错抛异常就会乱跳。这会导致我们跟踪调试时以及分析程序时,比较困难。
5. 异常会有一些性能的开销。当然在现代硬件速度很快的情况下,这个影响基本忽略不计。
6. C++没有垃圾回收机制,资源需要自己管理。有了异常非常容易导致内存泄漏、死锁等异常安全问题。这个需要使用RAII来处理资源的管理问题。学习成本较高。
7. C++标准库的异常体系定义得不好,导致大家各自定义各自的异常体系,非常的混乱。
8. 异常尽量规范使用,否则后果不堪设想,随意抛异常,外层捕获的用户苦不堪言。所以异常规范有两点:一、抛出异常类型都继承自一个基类。二、函数是否抛异常、抛什么异常,都使用 func()
throw();的方式规范化。
总结:异常总体而言,利大于弊,所以工程中我们还是鼓励使用异常的。另外OO的语言基本都是用异常处理错误,这也可以看出这是大势所趋。

【Java】异常 try-catch throw 详解 阅读详情

相关推荐

c++中try catch的用法

  在c++中,可以直接抛出异常之后自己进行捕捉处理,如:(这样就可以在任何自己得到不想要的结果的时候进行中断,比如在进行数据库事务操作的时候,如果某一个语句返回SQL_ERROR则直接抛出异常,在catch块中进行事务回滚(回滚怎么理解?))。 #include <iostream> #include <exception> using nam...

dinaoju5134的博客 6376

『C++』异常详解

C++异常详解

枫叶先生的博客 2247

C++——异常处理机制(try/catch/throw)

C++ 中的异常处理机制允许开发者编写健壮的应用程序,能够在遇到错误时优雅地处理这些问题。通过使用 try、catch 和 throw 关键字,可以有效地管理和处理程序中的异常情况。合理地使用异常处理机制,可以提高程序的健壮性和可维护性。

鲸落博客 874

【C++从青铜到王者】第二十三篇:C++异常

系列文章目录 文章目录系列文章目录前言一、C语言传统的处理错误的方式二、C++异常概念三、异常的使用1.异常的抛出和捕获2.异常的重新抛出3.异常安全4.异常规范四、自定义异常体系五、C++标准库的异常体系六、异常的优缺点1.C++异常的优点:2.C++异常的缺点:总结 前言 一、C语言传统的处理错误的方式 #define _CRT_SECURE_NO_WARNINGS 1 #include<iostream> #include<vector> using namespa.

森明帮大于黑虎帮的博客 1173

msf使用木马控制android手机

使用msfvenom生成木马控制手机

my_name_is_sy的博客 3520

Ubuntu断网环境下的系统更新:apt-offline保姆级教程(附常见问题排查)

本文详细介绍了在Ubuntu断网环境下使用apt-offline进行系统更新的完整教程,包括环境准备、签名文件生成、数据传输方案对比及常见问题排查。特别适用于企业级开发环境或安全敏感场景,帮助运维人员高效完成离线系统更新,确保系统安全与稳定。

weixin_29214691的博客 358

C++异常处理try/catch/throw

C++异常处理try/catch/throw 异常:程序运行时出现的错误 异常处理:即对有可能发生异常的地方做出预见性的安排 基本思想:主逻辑与异常处理分离 关键字: try{...主逻辑...}//尝试 catch{...异常处理逻辑...}捕获 //try和catch可以是一对多的关系,根据不同的异常做相应的处理 throw//抛出异常 例如: try { f1();//f1抛出异常后,其...

鬼谷子的博客 355

TBOX(Telematics Box)在智能网联汽车中的核心功能与应用场景解析

TBOX(Telematics Box)是智能网联汽车的“中枢神经”,基于Android或Linux操作系统,并通过CAN总线与车辆深度交互。它实现了远程控制、车辆状态监控、OTA升级及紧急呼叫(E-CALL)等核心功能,是提升用车安全、便利性与实现车辆持续进化的关键技术组件。

weixin_29158413的博客 800

bRPC:如何不写线程池就稳扛50万QPS(附调优清单)

一个慢请求把其他 IO 线程全部拖住,这种场景你敢在高峰期复现吗?C++ 高并发服务里,线程模型与连接管理往往直接决定了系统的尾延迟。bRPC 是一个工业级的 C++ RPC 框架(名字取自 "better RPC"),支撑了搜索、存储、推荐等场景,线上实例规模超过百万台。它把请求处理搬进用户态轻量线程,并用 Server、Channel、Controller 三个核心类就搭出多协议服务。 ##

gitblog_02496的博客 490

Windows系统3D Gaussian Splatting环境搭建全攻略:从零开始到成功运行

本文详细介绍了在Windows系统上搭建3D Gaussian Splatting环境的完整流程,包括CUDA 12.6安装、Anaconda环境配置、代码获取与依赖安装等关键步骤。针对Windows平台特有的环境配置问题,提供了实用的解决方案和常见错误排查方法,帮助开发者快速实现3D Gaussian Splatting的成功运行。

weixin_30832143的博客 452

将AAL图谱对应到Yeo7大网络中【原理,代码分析】

本文介绍了将AAL2图谱映射到Yeo7大功能网络的方法。通过整合皮层(Yeo2011)、小脑(Buckner2011)和纹状体(Choi2012)三个区域的功能网络图谱,采用投票机制确定每个AAL区域的网络归属。具体步骤包括:1)统计每个AAL区域体素在各网络图谱中的分布;2)选择体素数量最多的网络作为该区域的最终标签。该方法实现了从解剖结构到功能网络的映射,可获得120个AAL区域对应的7大功能网络标签。

yes666666的博客 2203

《C++ 异常处理:throw/try/catch + 栈展开 + RAII + 标准库》

本文系统介绍了 C++ 异常处理机制,对比 C 语言错误码方式,阐述了异常在信息丰富性、强制性和自动传播方面的优势。文章详细解析了 throw/try/catch 语法、异常传播时的栈展开机制、catch 的匹配规则(包括四种隐式转换),并通过自定义异常类继承体系展示了工程化异常处理方案。同时强调了异常与 RAII 资源管理的协同工作,以及 noexcept 规范的使用场景。全文通过丰富代码示例,帮助开发者全面掌握 C++ 异常处理的精髓,构建更健壮的程序。(149字)

2403_87581574的博客 420

【MBD开发】Simulink中的枚举

01 什么是枚举 按百度百科的词条【枚举】是在编程语言中用来存储一组固定的常量。不同编程语言的枚举语法也不一样,以C语言为例。 typedef enum{ GEAR_P, //0:P挡 GEAR_R, //1:倒挡 GEAR_N, //2:空挡 GEAR_D, //3:前进}_GEAR; 上面枚举了一个_GEAR数据,用GEAR_P表示0,GEAR_R表示1……​​​​​​​ if(current_gear==GEAR..

f6723的博客 3095

C++ 第四阶段 异常处理 - 第一节:try/catch/throw机制

摘要:本文系统介绍了C++异常处理机制,包括基本语法(try/catch/throw)、工作原理及标准异常类型(如runtime_error、bad_alloc等)。重点阐述了如何通过继承std::exception创建自定义异常类,并给出异常处理与RAII模式、智能指针结合的实践示例。文章强调异常处理的最佳实践,包括避免过度使用、优先捕获具体异常、遵循RAII原则等,同时推荐使用Valgrind等工具进行异常安全检测。通过异常机制可以提升程序的健壮性,但需注意性能开销和资源管理问题。

弘羽 870

Unity零基础到进阶 ☀️| Unity中的 GC及优化 超级全面解析 ☆(ゝω・)v 建议收藏!

介绍: 在游戏运行的时候,数据主要存储在内存中,当游戏的数据在不需要的时候,存储当前数据的内存就可以被回收以再次使用。内存垃圾是指当前废弃数据所占用的内存,垃圾回收(GC)是指将废弃的内存重新回收再次使用的过程。 Unity中将垃圾回收当作内存管理的一部分,如果游戏中废弃数据占用内存较大,则游戏的性能会受到极大影响,此时垃圾回收会成为游戏性能的一大障碍点。 本文我们主要学习垃圾回收的机制,垃圾回收如何被触发以及如何提GC收效率来提高游戏的性能。 Unity内存管理机制简介 要想了解垃圾回收如何工作以及何时被

努力前行,总会成为自己心中的那道光 6万+

Android12 适配 usb 触屏

在 Android 系统中,输入设备 IDC(Input Device Configuration)设备描述文件(.idc)是用于配置和定义输入设备行为和属性的文本文件。 该文件通常在`/system/usr/idc/` 或 `/vendor/usr/idc/`,具体位置因芯片厂商SDK而异。一般情况此类文件是预置到系统,开发者 root 权限才能修改这些文件。输入设备 IDC 设备描述文件在 Android 系统中起到了识别、配置、映射和定制输入设备的作用,使得系统能够准确解析和处理各种输入设备的事件,提

weixin_35723192的博客 1229

C++编程中的异常处理机制:try/catch/throw详解

C++中的异常处理机制为程序在面对运行时错误时提供了强大的支持。通过合理使用trycatch和throw,开发者可以编写出更加健壮、可维护的代码。理解并掌握异常处理机制,对于提高C++编程水平具有重要意义。希望本文的介绍能够帮助读者更好地理解和运用C++中的异常处理机制。

381

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

<span class=“js_title_inner“>C++异常处理机制 try-catch-throw</span>

我们所设计的函数在运行过程中出现异常是一件十分正常的事,有些异常是我们在设计时可以预见并且是可以进行恢复的,由于异常的发生往往比较底层,异常通常不能在当前层次的函数调用中就地恢复,而是需要上报到之前的函数调用中处理,为了实现这个目的,我们在C语言的实践中,往往可以设计一个错误码,将错误码层层上报,直到某层可以处理错误码。如果引发的异常的类型是类,它还具有基类(或类),则它可由接受异常类型的基类和对异常类型的基的引用的处理程序捕获。:是异常类型的具体类名。的类型,但 C++ 使您能够引发任何类型的异常。

marlos的博客 580

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

C/C++基础 异常处理关键字 throw、try、catch

C/C++基础 异常处理关键字 throw、try、catch

qq_34761779的博客 700

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

C++ 中的异常处理机制try/catch/throw

try块:用于存放被激活的特定异常。catch块:需要处理的位置,捕获异常。指定想要捕捉的异常类型throw块:出现问题时,抛出异常。操作数可以是任意的表达式//可以尝试多种异常捕捉 try { // 保护代码 }catch( ExceptionName e1 ) { // catch 块 }catch( ExceptionName e2 ) { // catch 块 }catc...

愤怒的小兵 582

C/C++编程异常处理中try和throw以及catch语句的用法

这篇文章主要介绍了C++编程异常处理中try和throw以及catch语句的用法,包括对Catch块的计算方式的介绍.       若要在 C++ 中实现异常处理,你可以使用 try、throw 和 catch 表达式。 首先,使用 try 块将可能引发异常的一个或多个语句封闭起来。 throw 表达式发出信号,异常条件(通常是错误)已在 try 块中发生。你可以使用任何类型的对象作为

qq_30096641的博客 1910

C/C++进阶学习笔记(三) 异常处理 try catch throw

本节介绍C++里面的异常处理

hosea1008的专栏 5422

C++的try_catch异常

大部分内容转自:http://blog.youkuaiyun.com/codestinity/article/details/6877581 一、简单的例子 首先通过一个简单的例子来熟悉C++ 的 try/catch/throw: #include //包含头文件 #include double fuc(doub

wonder 1万+

c++异常Try catch

一、简单的例子 首先通过一个简单的例子来熟悉C++ 的 try/catch/throw: 1 #include //包含头文件 2 #include 3 double fuc(double x, double y) //定义函数 4 { 5

ghevinn欢迎您光临 9642

C++ 的 try/catch/throw

一、简单的例子 首先通过一个简单的例子来熟悉C++ 的 try/catch/throw: 1    #include                                 //包含头文件 2    #include 3    double fuc(double x, double y)                        //定义函数 4    { 5   

wangzhen0331的专栏 682
上一篇: 【C语言】printf函数参数压栈问题
下一篇: 【C语言】sizeof(数组名),包括 一维数组、字符数组、二维数组
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值