c++异常处理的实现

C++异常处理实现(libstdc++) 为了更好的理解C++中异常处理的实现,本文简单描述了Itanium ABI中异常处理的流程和llvm/libsdc++简要实现。 阅读详情

 

我们编写的程序一般要满足正确性、健壮性、易读性和可复用性、可扩展性。健壮性指程序既能处理正确流程的情况,也能处理非法的错误的异常情况,提示用户出现了什么问题,一般由异常处理实现。在编写小型的程序时,可以很容易发现程序的错误,异常提示显得不那么重要,但在大型的由多人共同完成的程序中往往难以发现出现了什么问题,因此异常提示和处理显得尤为重要。下面我们了解c++的异常处理的实现。

异常机制提供程序中错误检测和错误处理部分之间的通信。C++的异常处理中包括:

throw表达式:错误检测部分抛出一个异常,说明程序遇到了无法处理的问题

try块:错误处理部分使用它处理异常。try语句块以try关键字开始,并以一个或多个catch子句结束。在try块中执行的代码所抛出的异常,通常会被其中一个catch子句处理。

由标准库定义的一组异常类,用来在throw和catch之间传递有关的错误信息。exception头文件定义了最常见的异常类,它的类名是exception,stdexcept头文件定义了几种常见的异常类,new头文件定义了bad_alloc异常类,提供因无法分配内存而由new抛出的异常,type_info头文件定义了bad_cast异常类。exception,bad_allo, bad_cast只定义了默认构造函数,其他的异常类型则只定义了一个使用string初始化的构造函数,用于提示错误信息,异常类型只定义了一个what操作,这个函数没有参数,返回const char*类型,为该一场提供文字信息。异常类的继承层次如下图所示:

我们来看一个例子

int triangle(int a, int b, int c)

{

       if(a<0 || b<0 || c<0 || a+b<=c || a+c<=b || b+c<=a)

              throw runtime_error("The lengths of three sides can't form triangle");

       return a + b + c;

}

 

int main()

{

       int total = 0;

       try

       {

              total = triangle(3,4,7);

       }

       catch(const runtime_error& e)

       {

              cout<<e.what()<<endl;

       }

       cout<<total<<endl;

       return 0;

}

函数int triangle(int a, int b, int c)求三角形三边之和,函数首先判断这三条边能否构成一个三角形,不能就抛出一个异常转入异常处理块中。

异常是通过抛出(throw)对象而引发的,该对象的类型决定应该激活哪个catch子句,被选中的代码是调用链中与该对象类型匹配且离抛出异常位置最近的的那个。异常以类似于将实参传递给函数的方式抛出和捕获。

执行throw的时候,不会执行跟在throw后面的语句,而是将控制从throw转到匹配的catch,该catch可以是同一函数中局部的catch,也可以在直接或间接调用发生异常的函数的另一个函数中。控制从一个地方转移到另一个地方,有两个重要含义:

(1)       沿着调用链的函数提早退出

(2)       一般而言,在处理异常的时候,抛出异常的块中的局部存储不存在了。

抛出异常时对象为指针解引用形式时,异常对象的类型与指针的静态类型相同,不论指针是否指向其派生类型。通常抛出指针是个坏主意,发生异常时抛出异常块的局部存储被释放了。

抛出异常的的时候,暂停当前函数的执行,开始查找匹配的catch子句,首先检查throw本身是否在try块内,如果是,检查与该try相关的catch子句,看是否其中之一与被抛出的对象匹配。如果找到匹配的catch,就处理异常,如果找不到,就退出当前函数,并且继续在调用函数中查找。这个过程称为“栈展开”

栈展开期间,提早退出包含throw的函数和相关的调用它的函数,每个函数中的局部对象都会撤销,如果是类类型的,就调用其析构函数。考虑这个问题,如果在调用析构函数时跑出了新的异常,编译器怎么办?是取代旧的异常还是忽略新的异常?当然,析构函数应保证不会抛出异常。

构造函数有可能会抛出异常,甚至发生在初始化表中。为了处理来自构造函数初始化表的异常,必须将构造函数初始化为函数测试块。可以使用函数测试块将一组catch子句与函数连成一个整体。

template<class T> Handle<T>::T(T* p)

try:ptr(p),use(new size_t(1))

{

}

catch(const bad_alloc& e)

{

handle_out_of_memory(e);

}

如果最终没有找到匹配的catch子句,则调用库函数terminate.

catch子句的匹配:比实参和形参的匹配规则更严格,大部分转换都不允许,出下面几个可能的区别之外,允许从非const到const的转换,允许从派生类型到基类类型的转换,将数组转化为指向数组类型的指针,将函数转化为指向函数类型的适当指针。

异常说明符:异常对象本身是抛出对象的副本,是否再次复制取决于异常说名符(其实就是catch形参)。基类的异常说明符可以捕获派生类的异常对象,而且,异常说明符的静态类型决定catch子句可以执行的动作。如果被抛出的对象类型是派生类型的,但由接受基类型的catch子句处理,那么catch不能使用派生类的特有的成员函数。

catch子句的顺序必须反映类型层次。

有可能单个catch不能完全处理一个异常,在进行了一些矫正行动后,catch可能确定该异常必须有函数调用链中更上层的函数处理,catch可以通过重新抛出将异常传递给函数调用链中更上层的函数。重新抛出是后面不跟类型或表达式的一个throw,

throw;

空throw语句将重新抛出异常,他只能出现在catch或从catch调用的函数中。被抛出的异常是原来的异常对象,而不是catch形参。

捕获所有异常的catch子句为:

catch(…)

{

 

}

异常说明:跟在函数形参表之后,在关键字throw后跟着一个(或为空)由圆括号括住的异常类型列表。

void recoup(int) throw(runtime_error);

空说明列表指出函数不抛出任何异常。

void no_problem() throw();

如果一个函数没有指出异常说明,则该函数可以抛出任意类型的异常。

异常说明有用的一种情况是,如果函数可以保证不抛出任何异常。

派生类虚函数的异常说明符必须比对应基类虚函数的异常说明符同样严格,或者更受限。

可以在函数指针的定义中提供异常说明符,在用另一指针初始化带异常说明的函数指针,或者将后者赋值給函数地址的时候,两个指针的异常说明符不必相同,但是,源指针的异常说明符必须至少与目标指针的一样严格,甚至更严格。

void (*pf)(int) throw() = recoup;                //error

 

C语言中的异常处理实现:cpp-CException 本文还有配套的精品资源,点击获取 简介:在C++中,异常处理是核心特性之一,而C语言并不直接支持这一功能。本项目“cpp-CException”提供了一种C语言中的异常处理实现方式,通过CException库模拟了C++中的 try 、 catch 和 throw 关键字。库内含有宏定义、异常类定义以及栈回溯功能,使得开发者可以在C... 阅读详情

相关推荐

深入理解Java和C++中的异常处理及JCoCo实现

本文探讨了Java和C++中异常处理机制的异同,以及JCoCo解释器在Java中的实现细节。文章首先比较了Java和C++在异常处理上的相似性,阐述了C++中缺乏垃圾收集机制,导致其在处理异常时需要额外的代码。接着,通过CoCo解释器的实现,展示了异常处理如何用于迭代控制。文章还介绍了信号处理机制,这是C语言版本的异常处理方式。最后,文章深入分析了JCoCo的Java实现,特别是扫描器和解析器的工作原理,包括它们如何处理CASM文件和构建抽象语法树。

weixin_29138345的博客 352

c++之异常处理

c++异常处理

weixin_59412612的博客 1714

VC++异常处理实现原理

关于VC++异常处理的详细中文文档,非常好的文档,对于GNU的异常处理有借鉴意义,而且原理很像

C++ 异常处理

C++标准库当中的异常也是一个基础体系,其中exception就是各个异常类的基类,我们可以在程序中使用这些标准的异常,它们之间的继承关系如下:std::exception 该异常是所有标准C++异常的父类。std::bad_alloc 该异常可以通过new抛出。std::bad_cast 该异常可以通过dynamic_cast抛出。std::bad_exception 这在处理C++程序中无法预期的异常时非常有用。

风间琉璃的博客 8720

映泰TB250-BTC主板魔改BIOS支持8/9代CPU实战与开机故障排查

BIOS(基本输入输出系统)是计算机硬件与操作系统之间的桥梁,负责初始化硬件和提供运行时服务。其工作原理是通过存储在主板芯片中的固件程序,在上电自检(POST)阶段完成对CPU、内存等关键组件的检测与配置。魔改BIOS的技术价值在于突破硬件限制,通过修改微码和电源管理模块,让旧平台支持新处理器,从而以极低成本实现性能跃升,在预算有限或追求极致性价比的DIY、办公和软路由等应用场景中极具吸引力。本文以映泰TB250-BTC矿板为例,详细解析了通过软刷方式刷入魔改BIOS,并重点解决了刷写后常见的“开机风扇转一

weixin_29164185的博客 405

IB网络下不同租户业务隔离方案

IB(InfiniBand)网络隔离可以在不同的通信模式下实现,其中包括 IPoIB(IP over InfiniBand)通信模式。在 IPoIB 模式下,InfiniBand 网络可以承载 IP 数据包,使得基于 IP 的应用程序能够在 InfiniBand 网络上进行通信。在这种情况下,IB 网络隔离通常指通过配置 Partition Key(PKey)来实现不同的租户或应用程序之间的网络隔离。然而,IB 网络隔离并不仅限于 IPoIB 模式。

guganly的专栏 1527

C++中 异常处理的 实现方式

1、异常是什么? 程序执行期间出现的错误或意外情况。   2、传统的异常处理方式 条件判断、分支处理 if 优点:实现简单直观 缺点:a、种类及情况太多,在大型系统中很难全部考虑到,导致程序崩溃,终止运行 b、某些异常情况的发生具有随机性,无法在程序中做出明确的处理,但是我们有时候又希望程序能够跳过异常部分错误运行。 c、我们希望可以传递异常信息,也就是发生

做一个快乐的人 957

别再乱调栅极电阻了!手把手教你用示波器调试FOC驱动MOS管,避开EMC和震荡坑

本文详细介绍了FOC驱动中MOS管栅极参数的精准调试方法,涵盖示波器配置、波形特征分析及栅极电阻选型策略。通过实战案例和工程经验,帮助工程师有效解决EMC和震荡问题,提升驱动电路稳定性和效率。

weixin_28728495的博客 502

C++中处理异常的方法及代码演示

异常处理就是处理程序中的错误。所谓错误是指在程序运行过程中发生的一些异常事件。

weixin_58796863的博客 690

逆强化学习:从专家示范中学习策略

逆强化学习(Inverse Reinforcement Learning,简称IRL)是强化学习(Reinforcement Learning,简称RL)的一个子领域,它的目标是从专家的行为中学习策略。在传统的强化学习中,智能体通过与环境交互,根据奖励信号来学习一个策略。而在逆强化学习中,我们没有直接的奖励信号,而是通过观察专家的行为来推断出奖励函数,从而学习到一个与专家类似的策略。逆强化学习作为强化学习的一个重要子领域,在许多实际应用场景中都取得了显著的成功。

AI天才研究院 1448

【部署】Docker部署OpenClaw及常见问题解决(win11)

给AI单独开一个隔离的小容器,AI执行所有命令、下载文件都在这个小盒子里,就算AI被诱导执行危险命令,也不会影响你Win11本机的文件和系统,是必开的安全功能。Docker容器里的OAuth回调,会尝试在你Win11本机的1455端口捕获认证信息,但容器和Win11本机的网络隔离,导致浏览器访问不到这个回调地址。「挂载」就是把你Win11本机的文件夹,共享给容器里的「虚拟小电脑」,两边都能读写文件,比如你想让AI操作你D盘里的代码文件,就需要挂载。

海兰 4696

C++中的异常处理

⼀般⼤型项⽬程序才会使⽤异常,下⾯我们模拟设计⼀个服务的⼏个模块每个模块的异常都是Exception的派⽣类,每个模块可以添加⾃⼰的数据最后捕获时,我们捕获基类的引用就可以了。下列程序要完整的运行成功就需要每个模块都调用成功,这里抛出异常的情况使用随机数取模进行模拟。

CSQCSQCC的博客 1571

数据结构课程设计--基于知识图谱的中医食疗数据管理与应用

【代码】数据结构课程设计--基于知识图谱的中医食疗数据管理与应用。

M_inherit的博客 565

C++编译器怎么实现异常处理1

C++编译器怎么实现异常处理 对于VC++实现异常处理的深入探讨 导论 相比较其他传统的语言,C++的一个变革的特征是支持异常处理。相对于传统语言的不清楚容易错误的错误处理机制,C++的异常处理是一个非常好的替代。在正常的代码和错误处理代码之间清楚的分割使得程序非常整洁和宜于维护。本文讨论编译器怎么实现异常处理。假设读者熟悉异常处理的语法。 本文包含一个异常处理的VC++的

sdssly的专栏 1404

为分析表明卡诺电池技术(或热泵式储电技术)-是目前最佳的储能技术!!!-2021年

卡诺电池(Carnot Battery)是一种基于热力学循环的储能技术,其核心原理是通过热力循环将电能转化为热能存储,并在需要时将热能重新转换为电能输出。这种技术得名于热力学中的卡诺循环原理,由法国工程师卡诺于1824年提出。

qq_15963745的博客 654

微信小程序 - 最新详细实现调起手机摄像头拍摄身份证人像面和国徽面取景框功能,在拍照相机上增加身份证证件照的轮廓或自定义文字,支持替换扫描拍摄辅助线图片及文本,小程序实现拍照身份证时带取景轮廓框拍摄!

微信小程序,身份证,证件照,人像,证件照提示框模板,vue身份证拍照框,摄像机相机里有引导内容,取景框拍摄,微信小程序实现拍照界面自定义实现,自拍人相框拍摄,取景框,户口簿取景框,画布指定区域生成图片,微信小程序身份证正反面拍照如何加入辅助图片引导照片,身份证取景框拍摄,服务器,上传,正反面,调起手机摄像头:拍摄身份证的正反面,自定义身份证取景框,在相机上绘制“身份证轮廓“与提示文字,拍摄身份证时出现人像框怎么实现,在相机上增加图片和文字,微信小程序怎么给调起的相机加入自定义图片,小程序实现给相机上面

🏆 前端领域优质创作者 1万+

C++ 异常处理机制的实现

介绍 相对于传统语言,C++ 的革命性特征之一,就是它对异常处理的支持。传统异常处理技术有缺陷并且易于出错,而 C++ 提供了一个非常优秀的替代方案。它将正常流程代码与错误处理代码清晰的隔离出来,使得程序更加健壮,易于维护。这篇文章将讨论编译器是如何实现异常处理的。假定读者已经对异常处理机制及其语法已经有了大致的了解。我用 VC++ 实现了本文中介绍的异常处理库。要将异常处理器替换成我的 VC+...

826

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

yaml-cpp容错解析架构深度解析:从异常处理到部分解析的C++实现

在复杂的软件系统中,配置文件解析的健壮性直接影响应用的稳定性。yaml-cpp作为C++生态中功能最完备的YAML解析库,其错误恢复机制设计巧妙,能够在遇到格式问题时依然保持最大程度的可用性。本文将深入剖析yaml-cpp的容错架构,揭示其如何在异常情况下实现部分解析与智能错误报告。 ## 异常处理体系架构设计 yaml-cpp构建了层次分明的异常处理体系,将错误分为三个主要类别: | 异常

gitblog_01084的博客 477

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

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

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

【链接】C++编译器是如何实现异常处理的

在Codeproject看到一篇好文,How a C++ compiler implements exception handling(C++编译器是如何实现异常处理的,但是仅讨论了VC),作者Vishai Kochhar(很奇怪的名字)。http://www.codeproject.com/KB/cpp/exceptionhandler.aspx作者在这篇文章里介绍Windows里的系统级异

lingol的专栏 597

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

C++异常处理的实现机制解析

C++ 的异常机制是如何实现的?请简要说明异常抛出、传递与处理的过程。C++ 异常机制是一种结构化的错误处理方案,它通过trythrow和catch实现错误的检测、抛出与捕获。异常机制使得,提高了代码的可维护性和健壮性。

陈子青的博客 352

C++编译器如何实现异常处理

译者注:本文在网上已经有几个译本,但都不完整,所以我决定自己把它翻译过来。虽然力求信、雅、达,但鉴于这是我的第一次翻译经历,不足之处敬请谅解并指出。 与传统语言相比,C++的一项革命性创新就是它支持异常处理。传统的错误处理方式经常满足不了要求,而异常处理则是一个极好的替代解决方案。它将正常代码和错误处理代码清晰的划分开来,程序变得非常干净并且容易维护。本文讨论了编译器如何实现异常处理。我将假

星仔的“韵” 1611

C++ Insights异常处理机制:try-catch块的底层实现

还在为C++异常处理的复杂性而头疼?想知道编译器是如何将你的try-catch代码转换为可执行形式的吗?C++ Insights这个神奇工具能让你一窥编译器背后的魔法! ## 异常处理的编译器视角 C++ Insights是一个基于Clang的源代码转换工具,它能展示编译器如何处理你的C++代码。对于异常处理机制,它揭示了try-catch块在编译器眼中的真实面貌。 ### try-catc

gitblog_00219的博客 672
上一篇: vs2008下wcecompat库的编译
下一篇: CxImage的使用
skilledprogrammer
博客等级 码龄19年 78粉丝 53原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值