1. 异常的概念

(1)程序在运行过程中可能产生异常

(2)异常(Exception)与Bug的区别

  ①异常是程序运行时可预料的执行分支

  ②Bug是程序是的错误,是不被预期的运行方式

2. 异常和Bug的对比

(1)异常:如运行时产生除0的情况、需要打开的外部文件不存在、数组访问时越界

(2)Bug:如使用野指针堆数组使用结束后未释放选择排序无法处理长度为0的数组

3. C语言经典处理方式:if-else

(1)示例程序

void func(…)
{
    if(判断是否产生异常)
    {
        正常情况代码逻辑
    }
    else
   {
        异常情况代码逻辑
    }
}

【编程实验】除法操作异常处理

#include <iostream>

using namespace std;

double divide(double a, double b, int* valid)
{
    const double delta = 0.000000000000001;
    ;

    if(!((-delta < b) && (b < delta)))
    {
        ret = a / b;
        *valid = ;  //正常
    }
    else
    {
        *valid = ;    //除0错误
    }
    return ret;
}

int main()
{
    ;
    , , &valid); //当第3个参数为NULL时,还是会出问题

    if(valid)
    {
        cout << "r = " << r << endl;
    }
    else
    {
        cout << "Divide by zero..." << endl;
    }

    ;
}

(2)缺陷

  ①divide函数有3个参数,难以理解其用途

  ②divide函数调用后必须判断valid代表的结果:true表示结果正常,false表示出现异常

4. C语言异常处理的优化方式

(1)通过setjmp()longjmp()进行优化

  ①包含头文件#include <setjmp.h>或<csetjmp>

  ②int setjmp(jmp_buf env):将当前上下文保存在jum_buf结构体中,以供以后longjmp()恢复状态信息时使用。如果是直接调用setjmp(),那么返回值为0;如果是由于调用longjmp()而调用setjmp(),那么返回值非0。setjmp()只能在某些特定情况下调用,如在if语句、 switch语句及循环语句的条件测试部分以及一些简单的关系表达式中。

  ③void longjmp(jmp_buf env, int val):用于恢复由最近一次调用setjmp()时保存到env的状态信息。当它执行完时,程序执行流会跳转到setjmp()那行,并根据重新执行setjmp(),但此时的setjmp()得到的返回值是val

【编程实验】除法操作异常处理优化

#include <iostream>
#include <csetjmp>  //for setjmp、longjmp();

using namespace std;

static jmp_buf env;  //须定义全局的上下文环境

double divide(double a, double b)
{
    const double delta = 0.000000000000001;
    ;

    if(!((-delta < b) && (b < delta)))
    {
        ret = a / b;
    }
    else
    {
        longjmp(env, ); //当错误发生时会跳转到setjmp那么的代码
                         //处,重新执行setjmp并把其的返回值设为1
    }
    return ret;
}

int main()
{

    ) //先保存上下文环境,刚调用时返回值为0
    {
        , );
        cout << "r = " << r << endl;
    }
    else
    {
        cout << "Divide by zero..." << endl;
    }

    ;
}

(2)缺陷

  ①引入setjmp()和longjmp()必然涉及到使用全局变量

  ②暴力跳转导致代码可读性降低

  ③本质还是if-else异常处理方式

5. C语言异常处理存在的通病

(1)会使程序逻辑中混入大量的处理异常的代码

(2)正常逻辑和异常处理代码混合在一起,导致代码迅速膨胀,难以维护。

【实例分析】异常处理代码分析

#include <iostream>

using namespace std;

#define SUCCESS            0
#define INVALID_POINTER   -1
#define INVALID_LENGTH    -2
#define INVALID_PARAMETER -3

int MemSet(void* dest, unsigned int length, unsigned char v)
{
    if(dest == NULL)
    {
        return INVALID_POINTER;
    }

    )
    {
        return INVALID_LENGTH;
    }

    ) || (v > ) )
    {
        return INVALID_PARAMETER;
    }

    unsigned char* p = (unsigned char*)dest;

    ; i< length; i++)
    {
        //将char赋值给int。
        //1.如果是char,则最高位为符号位,char赋值给int时会扩展最高位
        //2.如果是unsigned,则不会扩展,即低8位为char的值,其余24位为0
        p[i] = v;
    }

    return SUCCESS;
}

int main()
{
    ];
    );

    //正常处理与异常处理的代码混杂,不容易看出哪些是正常处理时的代码
    //哪些是异常发生时应处理的代码(特别是当返回值用数字表示,而不是这里有意义的常量名时)
    if(ret == SUCCESS)
    {
    }
    else if(ret == INVALID_POINTER)
    {
    }
    else if(ret == INVALID_LENGTH)
    {
    }
    else if(ret == INVALID_PARAMETER)
    {
    }

    ;
}

6. 小结

(1)程序中不可避免的会发生异常

(2)异常是在开发阶段就可以预见的运行时问题

(3)C语言中通过经典的if-else

(4)C++中存在更好的异常处理方式

第63课 C语言异常处理的更多相关文章

  1. go语言异常处理

    go语言异常处理 error接口 go语言引入了一个关于错误错里的标准模式,即error接口,该接口的定义如下: type error interface{ Error() string } 对于要返 ...

  2. Go语言异常处理defer\panic\recover

    Go语言追求简洁优雅,所以,Go语言不支持传统的 try…catch…finally 这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱.因为开发者很容易滥用异常, ...

  3. [原创]零基础R语言教程---第二课---R语言入门

    这节教程简单描述了R语言中常用的数据类型, 向量,字符串,矩阵,列表,数据框,以及附带了一个小例子 对于这节课所附带的例子需要做下列补充: 1.这个例子面向于对整列的数据进行预测 2.如果你需要求单行 ...

  4. c语言异常处理机制

    异常处理机制:setjmp()函数与longjmp()函数 C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数的特性来实现异常. 所 ...

  5. 第一课 C语言简明教程

    1序言: 1与Java.C#等高级语言相比,C语言使用简单但是也非常重要更容易出错,到目前为止基本上操作系统的内核代码超过百分之九十使用C语言完成,因此学好C语言是学好计算机这门课程的基础,特别是进入 ...

  6. 3.06课·········C#语言基础

    Main函数: static void Main(string [] args){ }程序代码需要写在Main函数的花括号内. 一.输出:Console.WriteLine("这是我的第一个 ...

  7. C++_系列自学课程_第_9_课_C语言风格字符串_《C++ Primer 第四版》

    前面说了写关于数组和指针的内容,这次在这里讨论一下字符串,讨论一下C语言风格的字符串. 在C语言里面我们利用字符数组来对字符串进行处理, 在C++里面我们前面说过一种类类型string可以对字符串进行 ...

  8. Asp.Net Web API 2第七课——Web API异常处理

    前言 阅读本文之前,您也可以到Asp.Net Web API 2 系列导航进行查看 http://www.cnblogs.com/aehyok/p/3446289.html 本文主要来讲解Asp.Ne ...

  9. C语言异常处理和连接数据库

    #include <stdio.h> #include <setjmp.h> jmp_buf j; void Exception(void); double diva(doub ...

随机推荐

  1. .net c# 视频剪切抓取缩略图

    public string Cut(string ffmpegPath, string videoPath, string savePath, string imgSize, int sleepTim ...

  2. nodejs--实现跨域抓取数据

    最近公司安排给我一个任务,抓取页面数据:http://survey.finance.sina.com.cn/static/20205/20131120.html?pid=20205&dpc=1 ...

  3. tmtTable设计说明文档

    文件链接:tmt-table.js BOSS后台项目用到最多的就是列表页,所以把列表页做成通用组件,可以大大提高开发效率. 因为列表可能有不同的样式,所以在实例化组件时可以传值控制样式,用这种方式: ...

  4. HTML标签的嵌套

    随着时间的推移,我们学习html的基础知识有了大概的了解.而我发现,平时在写html文档的时候,发现不太清楚标签之间的嵌套规则,经常是想到什么标签就用那些,然而发现有时的标签嵌套却是错误的.通过网上找 ...

  5. ABAP--关于ABAP流程处理的一些命令的说明(stop,exit,return,check,reject)

    Stop 命令 使用该命令的程序位置 INITIALIZATION, AT SELECTION-SCREEN, START-OF-SELECTION和GET 事件中 处理说明 1. 当在INITIAL ...

  6. sql联合查询

    联合查询效率较高.以下例子来说明联合查询的好处 t1表结构(用户名,密码)    userid int         username   varchar(20)     password      ...

  7. objective-c系列-单例

    // 地球只有一个,所以声明一个地球对象就可以了,千万不能声明两个啊!同理,有时候一个类也有只能有一个对象的情况,例如服务器,只想存到一个里 // 面,这样子,下次才可以取出上次存的数据. //用全局 ...

  8. 使用AndroidStudio进行NDK开发简单配置

    1. 准备工作 在实际写代码之前,首先我们还是需要做一些准备工作: 下载NDK开发包:Android官方下载页面 配置系统环境变量 下载好NDK开发包之后,直接解压到任意目录,然后需要配置一下系统环境 ...

  9. 【代码笔记】iOS-手机验证码

    一,效果图. 二,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController : UIVi ...

  10. 【代码笔记】iOS-点击搜索跳转到另外一个页面

    一,效果图. 二,工程图. 三,代码. RootViewController.h #import <UIKit/UIKit.h> @interface RootViewController ...