异常处理---C语言

程序消亡的一般形式

  • 无疾而终(正常退出,例如return 0、点击图标按钮退出)
  • 自杀(例如:abort()、exit(0))abort会弹出终端后中断,exit直接一闪而过中断,断言assert可以用abort模拟实现
  • 他杀(任务管理器中关闭该程序)

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

  1. 终止程序
#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()存在以下的缺陷

  1. 函数的使用者必须非常靠近函数调用的地方编写错误代码,无疑使代码臃肿笨拙
  2. setjmp() 和longjmp()并不能够很好的支持C++面向对象的语句
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值