【C++】异常简述(一):C语言中的异常处理机制
人的一生会遇到很多大起大落,尤其是程序员.
程序员写好的程序,论其消亡形式无非三种:无疾而终、自杀、他杀.
当然作为一名程序员,最乐意看到自己写的程序能够无疾而终,因此尽快的学习异常处理机制是非常重要的!
使自己的程序在遇到错误时能够克服错误,更健壮,而不是遇到错误就愤愤自杀.
因此,在简述C++的异常机制之前,本文先来简述一下C语言中的异常处理机制.
在C语言中,传统的错误处理方式有如下几种:
1.直接终止程序(自杀)
例如:
int main(){
int a = 10;
int b = 20;
int c = a/0;
return 0;
}
当用gcc编译完后,执行,会打印“浮点数例外”,然后程序结束.
这种情况是不允许的,无条件终止程序的库无法运用到不能当机的程序里。
2.返回一个错误的值,附加错误码
这种错误处理方式也很常见,比如我们用C语言打开一个文件失败时:
#include<stdio.h>
#include<errno.h>
int main(){
FILE* fp = fopen("test.txt","r");
if(NULL == fp){
printf("文件打开失败,错误码:%d\n",errno);
}
return 0;
}
因为我当前处于Linux系统下,没有GetLastError()函数,所以在Linux下使用全局变量errno来演示.
这种情况,比较常用,但是有时不合适,例如返回错误码是int,每个调用都要检查错误值,极不方便,也容易让程序规模加倍
3.返回一个合法的值,让程序处于某种非法的状态
这种例子,最常见的就是atoi函数,例如:
#include<stdio.h>
#include<stdlib.h>
int main(){
int a = atoi("123456789");
int b = atoi("dasdasdcs");
printf("a = %d\n",a);
printf("b = %d\n",b);
return 0;
}
虽然b为0,但是有一个全局变量表示了这个0属于非法值,不是由字符串0转过来的.
这种情况,很容易误导调用者,万一调用者没有去检查全局变量errno或者通过其他方式检查错误,那是一个灾难,而且这种方式在并发的情况下不能很好工作
4.调用一个预先准备好在出现"错误"的情况下使用的函数.
这种异常处理情况比较少见,那我就现场直编了一个:
#include<stdio.h>
#include<stdlib.h>
void DealError(){
printf("除数为0,老兄你在逗我?\n");
}
typedef void(*fun)();
int Div(int a,int b,fun callback){
if(b==0){
callback();
return 0;
}
return a/b;
} int main(){
printf("正常情况下的4/2 = %d\n",Div(4,2,DealError));
printf("调用错误处理函数的4/0 = %d\n",Div(4,0,DealError));
return 0;
}
5、通过暴力的方式解决
暴力的方式有两种,abort()函数和常见exit()函数.例如依然处理除0问题,代码可以这样写:
#include<stdio.h>
#include<stdlib.h>
int Div(int a,int b){
if(b==0){
//exit(1); //直接退出
abort(); //在Windows下会弹出一个信息框
}
return a/b;
} int main(){
printf("正常情况下的4/2 = %d\n",Div(4,2));
printf("调用错误处理函数的4/0 = %d\n",Div(4,0));
return 0;
}
6、使用goto语句
虽然,goto语句十分强大,但违背了程序的顺序执行,打乱的程序的执行流,盲目的使用goto语句可能会出现意想不到的错误,因此,并不推荐使用goto语句.
但,尽管如此,为了探索C语言的异常处理机制,我还是实现一下goto语句处理异常的代码.
#include<stdio.h>
#include<stdlib.h>
int main(){
int a = 0;
int b = 0;
printf("请输入两个值:\n");
printf("a = ");
scanf("%d",&a);
printf("b = ");
scanf("%d",&b);
if(b==0){
goto Error;
}
printf("a/b = %d\n",a/b);
return 0;
Error:
printf("除数不能为0,程序异常退出!\n");
exit(-1);
}
7、使用setjmp()与longjmp()
goto语句虽然可以跳来跳去,但标记与goto必须处于同一作用域内.
想从一个函数跳转到另一个函数,就必须使用setjmp与longjmp组合.
实例如下:
#include<stdio.h>
#include<setjmp.h> jmp_buf mark; int Div(int a,int b){
if(b==0){
longjmp(mark,1); //会使state = 1
}
return a/b;
}
int main(){
int State = setjmp(mark); //保存寄存器相关信息,初始值为0
if(State==0){
Div(4,0);
}else{
switch(State){
case 1:
printf("除0异常!\n");
}
}
return 0;
}
注意事项:
1、setjmp必须先调用,在异常位置通过调用longjmp以恢复先前被保存的程序执行点,否则将导致 不可预测的结果,甚至程序崩溃。
2、在调用setjmp的函数返回之前调动longjmp,否则结果不可预料。
setjmp与longjmp存在以下缺陷:
1、函数的使用者必须非常靠近函数调用的地方编写错误处理代码,无疑使代码变的臃肿笨拙。
2、setjmp()和longjmp()并不能够很好的支持C++面向对象的语义。
以上情况,便是C语言中的异常处理常见的机制,C++提供了更为完善的异常处理机制,我将在下文中简述.
【C++】异常简述(一):C语言中的异常处理机制的更多相关文章
- C语言中的异常处理机制
#define try if(!setjmp(Jump_Buffer)) 返回try现场后重新执行判断,所以有两次执行. http://blog.csdn.net/tian_dao_chou_qin/ ...
- Java语言中的异常处理
Java语言中的异常处理包括声明异常.抛出异常.捕获异常和处理异常四个环节. throw用于抛出异常. throws关键字可以在方法上声明该方法要抛出的异常,然后在方法内部通过throw抛出异 ...
- C语言中的异常处理
一 前言: 异常处理,对于做面向对象开发的开发者来说是再熟悉不过了,例如在C#中有 try { ... } catch( Exception e){...} finally{ ..... } 在C++ ...
- .NET中的异常处理机制(一)
1.异常处理的总体指导思想 学习C#中的异常处理机制,大概要了解以下几点: 首先,我们需要知道的事所有具体异常都是继承自System.Exception基类的. 其次,要熟悉FCL类库内置好的一些异常 ...
- 深入理解C++中的异常处理机制
异常处理 增强错误恢复能力是提高代码健壮性的最有力的途径之一,C语言中采用的错误处理方法被认为是紧耦合的,函数的使用者必须在非常靠近函数调用的地方编 写错误处理代码,这样会使得其变得笨拙和难以使用.C ...
- Java中的异常处理机制《》
异常机制已经成为判断一门编程语言是否成熟的标准,异常机制可以使程序中异常处理代码和正常业务代码分离,保证程序代码更加优雅,并提高程序健壮性. Java异常机制主要依赖于try.catch.finall ...
- C++中的异常处理机制
C++中的捕获异常机制catch参数中实参的类型不同,采取的处理方式则不相同,且与普通的函数调用还不一样,具体表现为当抛出异常throw A()或throw obj时,对象会进行一次额外的对象复制操作 ...
- 16、java中的异常处理机制
异常:就是程序在运行时出现不正常情况.异常由来:问题也是现实生活中一个具体的事物,也可以通过java的类的形式进行描述.并封装成对象. 其实就是java对不正常情况进行描述后的对象体现. 对于问题的划 ...
- Java中的异常处理机制的简单原理和应用
异常是指java程序运行时(非编译)所发生的非正常情况或错误,与现实生活中的事件很相似,现实生活中的事件可以包含事件发生的时间.地点.人物.情节等信息,可以用一个对象来表示,Java使用面向对象的方式 ...
随机推荐
- mysql03---触发器
触发器trigger:某条数据改变,希望其他数据也改变(一张表的数据改变,另一张表的数据也变).监测insert,update,delete.能够监测增删改并出发增删改. 监测点(table)监测事件 ...
- mac系统下显示隐藏文件
在终端上输入以下命令即可: 显示隐藏文件命令: defaults write com.apple.finder AppleShowAllFiles -bool true 不显示隐藏文件命令: defa ...
- 并不对劲的bzoj5342:loj2554:uoj401:p4566: [Ctsc2018]青蕈领主
题目大意 \(T\)(\(T\leq100\))组询问 有\(1\)到\(n\)(\(n\leq50000\))这\(n\)个整数组成的一个排列 定义这个排列的一个子区间是"连续" ...
- 【POJ 1155】TELE
[题目链接] 点击打开链接 [算法] 树形DP f[i][j]表示以i为根的子树中,选了j个叶子节点,所能带来的最大收益 不难发现这就是一个经典的背包问题,不过是在树上做背包罢了 最后,判断f[1][ ...
- bzoj 3872 [ Poi 2014 ] Ant colony —— 二分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3872 从食蚁兽所在的边向叶节点推,会得到一个渐渐放大的取值区间,在叶子节点上二分有几群蚂蚁符 ...
- Silverlight 后台利用代码触发 Button 的Click事件
页面上一个查询按钮,当用户点击 回车键 的时候 处罚查询按钮的onclick事件 public MainPage() { InitializeComponent(); this.KeyDown += ...
- centos 6.2 pptp 客户端 安装(转载)
转自:http://www.lnmpblog.com/archives/611 centos 6.2 64.bit的桌面版本.配置vpn客户端. 步骤: 1.yum -y install pptp 2 ...
- Akka源码分析-Akka Typed
对不起,akka typed 我是不准备进行源码分析的,首先这个库的API还没有release,所以会may change,也就意味着其概念和设计包括API都会修改,基本就没有再深入分析源码的意义了. ...
- 安装使用electron辛路历程
安装使用electron辛路历程 成功安装electron以及成功使用第一个应用,整整花费了我一整天的时间,各种百度,各种尝试.最终,终于总结了一个亲测可行的终极可执行方案: electron 简单介 ...
- [USACO 2011 Dec Gold] Threatening Letter【后缀】
Problem 3: Threatening Letter [J. Kuipers, 2002] FJ has had a terrible fight with his neighbor and w ...