前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++为什么要引入异常处理机制

C++为什么要引入异常处理机制

作者头像
恋喵大鲤鱼
发布于 2018-08-03 08:42:19
发布于 2018-08-03 08:42:19
1.2K00
代码可运行
举报
文章被收录于专栏:C/C++基础C/C++基础
运行总次数:0
代码可运行

1.异常处理的困难

在程序设计中,错误时不可避免的。及时有效的发现错误,并作出适当的处理,无论是在软件的开发阶段还是在维护阶段都是至关重要的。错误修复技术是提高代码健壮性的最有效的方法之一。

程序员往往忽视错误处理,并不是因为程序员认为自己的程序不会出错,而是因为错误处理不是一件轻松的事。编写错误处理代码,一方面会分散处理“主要”问题的精力,另一方面会引起代码膨胀,给阅读和维护带来困难。而且,尽可能详细地考虑出错的情形也是一件费时费力的事情。

2.C语言处理异常的常用方法

在C语言中,有一些处理错误的常用方法。例如,使用C标准库的宏断言assert()作为出错处理的方法。在开发过程中,使用这个宏进行必要的条件检测,项目完成后可以使用#define NDEBUG来禁用断言assert()。随着程序规模的扩大,使用宏来进行出错处理的复杂性也在增加。

如果在当前上下文环境中,程序猿可以明确地掌握每一个具体步骤的运行结果,出错处理就变得十分明确和容易了。若错误问题发生时在一定的上下文环境中得不到足够的信息,则需要从更大的上下文环境中提取出错误处理信息。C语言处理这类情况通常有三种典型的方法。

(1)出错的信息可以通过用函数返回值获得。如果函数返回值不能用,则可设置一全局错误判断标志(标准C语言中errno()和perror()函数支持这一方法)。由于对每个函数都进行错误检查十分繁琐,并增加了程序的混乱度,程序设计者可能简单地忽略这些出错信息。另外,来自偶然出现异常的函数的返回值可能并不能提供什么有价值的信息。

(2)可使用C标准库中一般不常用的信号处理系统,利用signal()函数(判断事件发生类型)和raise()函数(产生事件)。由于信号产生库的使用者必须理解和安装合适的信号处理,所以使用上述两个函数进行错误处理时应紧密结合各信号产生库。对于大型项目而言,不同库之间的信号可能会产生冲突。

(3)使用C标准库中非局部跳转函数:setjmp()和longjmp()。setjmp()函数可在程序中存储一典型的正常状态,如果程序发生错误,longjmp()可恢复setjmp()函数的设定状态,从而实现goto语句无法实现的“长跳转”。事先被存储的地点在恢复时,可以得知是从哪里跳转过来的,也就是说,可以确定错误发生的地点。

参考下面的使用setjmp()和longjmp()实现“长跳转”的例子。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include <setjmp.h>

#include <iostream>
using namespace std;

class Game{
public:
    Game(){
        cout<<"game()"<<endl;
    }
    ~Game(){
        cout<<"~game()"<<endl;
    }
};

jmp_buf jmpBuf;

void test(){
    Game game;
    for(int i=0;i<3;++i)
        cout<<"there is no interesting game"<<endl;
    longjmp(jmpBuf,1);  
    cout<<"after jump"<<endl;
}

int main(){
    if(setjmp(jmpBuf)==0){
        cout<<"one, two, three..."<<endl;
        test();
    }
    else
        cout<<"It is fantastic"<<endl;
}

程序输出:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
one, two, three...
game()
there is no interesting game
there is no interesting game
there is no interesting game
~game()
It is fantastic

setjmp()和longjmp()函数实现goto无法实现的非局部的跳转,其实原理很简单。

(1)setjmp(j)设置“jump”点,用正确的程序上下文填充jmp_buf对象j。这个上下文包括程序存放位置、栈和框架指针,其它重要的寄存器和内存数据。当初始化完jump的上下文,setjmp()返回0值。

(2)以后调用longjmp(j,r)的效果就是一个非局部的goto跳转或“长跳转”,程序将跳转到由j描述的上下文处(也就是到那原来设置j的setjmp()处)。当作为长跳转的目标而再次被调用时,setjmp()返回r或1(如果r设为0的话)。(记住,setjmp()不能在这种情况时返回0)。

程序中,控制流从函数test内部跳转到了main函数的setjmp()处,test函数中的cout<<"after jump"<<endl;并没有被执行。

3.C++为何引入异常处理机制

在早些时期,C++本身并没有处理运行期错误的能力。取而代之的是那些传统的C的异常处理方法。这些方法可以被归为三类设计策略:

(1)函数返回一个状态码来表明成功或失败; (2)把错误码赋值给一个全局标记并且让其他的函数来检测; (3)终止整个程序;

上述的任何一个方法在面向对象环境下都有明显的缺点和限制,如繁琐的检测函数返回值和全局的错误码,程序崩溃等。其中的一些根本就不可接受,尤其是在大型应用程序中。因此C++的异常处理就在这个背景下产生的。C++自身有着非常强的纠错能力,发展到如今,已经建立了比较完善的异常处理机制。

C++之父Bjarne Stroustrup在《The C++ Programming Language》中讲到:一个库的作者可以检测出发生了运行时错误,但一般不知道怎样去处理它们(因为和用户具体的应用有关);另一方面,库的用户知道怎样处理这些错误,但却无法检查它们何时发生(如果能检测,就可以在用户的代码里处理了,不用留给库去发现)。

Bjarne Stroustrup说:提供异常的基本目的就是为了处理上面的问题。基本思想是:让一个函数在发现了自己无法处理的错误时抛出(throw)一个异常,然后它的(直接或者间接)调用者能够处理这个问题。


[1]陈刚.C++高级进阶教程[M].武汉:武汉大学出版社,2008[P353-P355] [2]百度百科.setjmp [3]C++的异常处理

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2015年11月28日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
该文章介绍了C++异常处理机制,包括C语言错误处理方法、C++异常处理方法(使用throw, try, catch),并给出了具体的代码示例。
s1mba
2017/12/28
1.9K0
从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
在Android Native层实现Try/Catch异常处理机制
在Native层实现异常处理的关键在于信号处理(Signal Handling)和非局部跳转(Non-Local Jumps)。当程序发生错误(如访问非法内存、除以零等)时,操作系统会向进程发送一个信号。我们可以设置一个信号处理函数(Signal Handler),在收到信号时执行特定的代码。
陆业聪
2024/07/23
2890
在Android Native层实现Try/Catch异常处理机制
C/C++ 学习笔记八(断言与异常处理)
该文介绍了C语言中一些常见错误处理方式,包括断言、异常处理、错误码、setjmp/longjmp以及goto语句等。同时介绍了在编写代码时,应避免使用setjmp/longjmp和goto语句,以及使用错误码对错误进行处理。
Celebi
2017/08/28
2.6K0
C++异常处理机制
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。
南桥
2024/09/20
1310
C++异常处理机制
利用C语言中的setjmp和longjmp,来实现异常捕获和协程
在 C 标准库中,有两个威力很猛的函数:setjmp 和 longjmp,不知道各位小伙伴在代码中是否使用过?我问了身体的几位同事,一部分人不认识这两个函数,有一部分人知道这个函数,但从来没有使用过。
IOT物联网小镇
2021/05/13
2.2K1
利用C语言中的setjmp和longjmp,来实现异常捕获和协程
C++异常实现与longjmp, setjmp,栈指针EBP, Active Record
http://blog.csdn.net/smstong/article/details/50728022
用户7886150
2021/02/12
5330
C语言异常处理之 setjmp()和longjmp()
异常处理之除0情况 相信大家处理除0时,都会通过函数,然后判断除数是否为0,代码如下所示: double divide(doublea,double b) { const double delta = 0.00000000001; //由于浮点数不精确,所以需要定义个很小的数 if(!((-delta<b)&&(b<delta))) { return a/b ; } else { return 0;
诺谦
2018/04/16
1.1K0
小白学协程笔记2-c语言实现协程-2021-2-10
前面我们已经了解到协程的基本概念以及对称协程和非对称协程的定义,本节将对如何用c语言在用户态实现协程切换作以简单介绍。
用户7719114
2022/02/22
1.4K0
小白学协程笔记2-c语言实现协程-2021-2-10
C程序设计的异常处理
大家新年好,感谢大家对本公众号一如既往地支持,后面争取创作出更加优质的文章。今天是2021年的第一篇文章,分享一下在C程序设计当中对异常的处理。主要是介绍一下goto和longjmp函数的使用。
飞哥
2021/01/18
7610
【C++高阶】深入理解C++异常处理机制:从try到catch的全面解析
前言:在编程的浩瀚宇宙中,C++以其卓越的性能、强大的灵活性和对底层硬件的直接控制而著称,是无数开发者心中的瑰宝。然而,在追求高效与极致的路上,错误处理与异常管理往往成为不可忽视的重要环节。C++通过引入异常处理机制,为开发者提供了一套强大而灵活的工具,以优雅地应对程序执行过程中可能遇到的各种异常情况,从而确保程序的健壮性和可靠性
Eternity._
2024/08/09
1.2K0
【C++高阶】深入理解C++异常处理机制:从try到catch的全面解析
C/C++错误信息
在 C/C++ 编程中,错误信息的捕获和处理是保证程序健壮性的重要部分。错误通常通过函数的返回值或者全局变量 errno 来表示。为了方便调试和错误处理,C/C++ 提供了多种函数和方法来获取和输出错误信息。以下是 C/C++ 错误处理的常见方法及函数介绍:
ljw695
2025/03/22
1520
C++异常
注:实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误
用户9645905
2022/11/30
7320
C++异常
【C++】异常处理 ⑤ ( 异常类型 | 传统 C 语言中的异常处理 | C++ 异常处理 - 抛出 int 类型异常 | 捕获异常类型 / 异常变量 | C++ 异常处理 - 抛出指针类型异常 )
传统的 C 语言中 错误处理 , 是通过返回不同的 int 类型值进行的 , 如 :
韩曙亮
2023/12/02
4470
【C++】异常处理 ⑤ ( 异常类型 | 传统 C 语言中的异常处理 | C++ 异常处理 - 抛出 int 类型异常 | 捕获异常类型 / 异常变量 | C++ 异常处理 - 抛出指针类型异常 )
【编程基础】C++异常处理简介
遗憾的是,在实践中人们通常会忽略出错情况,就好像程序处在一个无错误的状态下进行工作的。毫无疑问,导致上述问题的一个原因就是,检测错误是一个乏味的工作并且导致代码的膨胀。比如:函数printf()返回那
程序员互动联盟
2018/03/13
7810
【编程基础】C++异常处理简介
C++异常的介绍和分析
C++11:异常 1.C语言传统的处理错误的方式 与 C++的对比 传统的错误处理机制: 终止程序,如assert,缺陷:用户难以接受。如发生内存错误,除0错误时就会终止程序。 返回错误码,缺陷:需要程序员自己去查找对应的错误。如系统的很多库的接口函数都是通过把错误码 放到errno中,表示错误 C 标准库中setjmp和longjmp组合。这个不是很常用,了解一下 实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。 c++处理方式 使
雪芙花
2022/10/31
8500
C++异常的介绍和分析
C++ 异常处理机制详解:轻松掌握异常处理技巧
C++ 异常处理机制允许程序在运行时处理错误或意外情况。它提供了捕获和处理错误的一种结构化方式,使程序更加健壮和可靠。
小万哥
2024/04/28
3920
C++ 异常处理机制详解:轻松掌握异常处理技巧
思科VPP系列专题十:协程模型
协程(英语:coroutine)是计算机程序的一类组件,推广了协作式多任务的子例程,允许执行被挂起与被恢复。相对子例程而言,协程更为一般和灵活,但在实践中使用没有子例程那样广泛。协程更适合于用来实现彼此熟悉的程序组件,如协作式多任务、异常处理、事件循环、迭代器、无限列表和管道。
通信行业搬砖工
2023/11/29
5890
思科VPP系列专题十:协程模型
【C++】你了解异常的用法吗?
实际中C语言基本都是使用返回错误码的方式处理错误,部分情况下使用终止程序处理非常严重的错误。
利刃大大
2025/05/21
1040
【C++】你了解异常的用法吗?
C++异常
异常是一种处理错误的方式,当一个函数发现自己无法处理的错误时就可以抛出异常,让函数的直接或间接的调用者处理这个错误。
用户11029129
2024/10/18
1600
C++异常
C++ 异常和错误处理机制:如何使您的程序更加稳定和可靠
异常处理是指在程序执行过程中发生异常或错误时,程序能够捕获并处理这些异常或错误的机制。例如,当程序试图访问一个未初始化的指针或除以零时,就会发生异常。异常处理的目的是确保程序能够在出现问题的情况下继续执行,并且能够提供有用的错误信息,以便于程序员进行调试和修复。
小万哥
2023/05/09
7930
C++ 异常和错误处理机制:如何使您的程序更加稳定和可靠
推荐阅读
相关推荐
从零开始学C++之异常(一):C语言错误处理方法、C++异常处理方法(throw, try, catch)简介
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验