您的位置:首页 > 编程语言 > C语言/C++

异常处理---C语言

2017-03-27 22:13 127 查看
程序消亡的一般形式

无疾而终(正常退出,例如return 0、点击图标按钮退出)

自杀(例如:abort()、exit(0))abort会弹出终端后中断,exit直接一闪而过中断,断言assert可以用abort模拟实现

他杀(任务管理器中关闭该程序)

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

终止程序

#include<stdio.h>
#include<windows.h>
#include<iostream>
using namespace std;
void FunTest()
{
int right = 0;
int ret = 5/right;//0不能做除数
}
int main()
{
FunTest();
int ret = GetLastError();
return 0;//程序会直接崩溃
}


2.返回一个表示错误的值,附加错误码(GetLastError()、errno、$err,hr)

int main()
{
FILE *fp = fopen("1.txt","rb");
cout<<errno<<endl;//errno低层是一个宏,表示错误码,此时输出结果为2
int ret = GetLastError();//输出结果为2
cout<<ret<<endl;
getchar();//或者使用$err,hr在监视里查看错误码和错误消息(系统里找不到指定的文件  2)
return 0;//404:404 是一个 http 错误代码,指的是网页不存在404 的含义:第一个 4 表示客户端出错,也就是服务器对你说:嘿,
//天堂有路你不走,404 无门你偏要闯进来;第二个 0 表示你把网址打错了;最后表示这个错误代码在 4 开头的错误代码中排行老四
}


3.返回一个合法的值,让程序处于某种非法的状态(坑爹的atoi),可见我前面的字符串转换为整型的博客字符串转换为整型

在我编写的程序中,定义了一个联合体变量VALID来对返回值进行标识,当返回0时,State变量若是VALID,则为合法结果,否则0是字符串非法

4.调用一个预先准备好在出现错误的情况下用的函数(回调函数)

5.暴力解决方式(abort()或则exit())

6.使用goto语句(缺点:打乱程序的正常执行,跳过一下变量的定义、不允许函数间的跳转)

7.setjmp()和longjmp()

#include<setjmp.h>
jmp_buf mark;//全局变量mark,保存当前信息的执行点
void FunTest1()
{
longjmp(mark,1);
}
void FunTest2()
{
longjmp(mark,2);
}
void FunTest3()
{
longjmp(mark,3);
}
int main()
{
int iState = setjmp(mark);
if(0==iState)
{
FunTest1();//一旦longjmp()函数跳到执行点后,后面的将不执行
FunTest2();
FunTest3();
}
else
{
switch(iState)
{
case 1:
cout<<"FunTest1()"<<endl;//因为此时是验证setjmp()和longjmp(),我们用输出代替,一般情况下这里是解决错误的语句
break;
case 2:
cout<<"FunTest2()"<<endl;
break;
case 3:
cout<<"FunTest3()"<<endl;
break;
}
}
getchar();//打印FunTest1()
return 0;
}


注意:

setjmp必须先调用,在异常位置通过调用longjmp以恢复先前被保存的程序执行点,否则会导致不可预测的结果,甚至程序崩溃

在调用setjmp的函数返回之前调动longjmp,否则结果不可预料

#include<setjmp.h>
jmp_buf mark;//全局变量mark,保存当前信息的执行点
void FunTest1()
{
longjmp(mark,1);
}
void FunTest2()
{
longjmp(mark,2);
}
void FunTest3()
{
longjmp(mark,3);
}
int main()
{
int iState = 0;//首先调用longjmp()函数
if(0==iState)
{
FunTest1();
FunTest2();
FunTest3();
}
else
{
switch(iState)
{
case 1:
cout<<"FunTest1()"<<endl;
break;
case 2:
cout<<"FunTest2()"<<endl;
break;
case 3:
cout<<"FunTest3()"<<endl;
break;
}
}
iState = setjmp(mark);
getchar();//程序崩溃,所以必须先调用setjmp()保存当前信息的执行点
return 0;
}


setjmp()和longjmp()存在以下的缺陷

函数的使用者必须非常靠近函数调用的地方编写错误代码,无疑使代码臃肿笨拙

setjmp() 和longjmp()并不能够很好的支持C++面向对象的语句
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  异常处理