c语言实现异常处理

一、异常的概念

  • 什么是异常?异常一般指的是程序运行期(Run-Time)发生的非正常情况。异常一般是不可预测的,如:内存不足、打开文件失败、范围溢出等,UNIX 使用信号给出异常,并当发生异常时转跳到信号处理过程进行异常处理。
  • 如果Linux内核本身或者新开发的Linux内核模块存在bug,产生了“除零”,“内存访问越界”、“缓冲区溢出”等错误,同样会由Linux内核的异常处理例程来处理。Linux内核通过在异常处理程序中判断,如果发现是“严重的不可恢复”的内核异常,则会导致“内核恐慌”(kernel panic),即Linux内核崩溃。

二、异常处理机制

异常都被认为是一种很优雅的处理错误的机制,异常处理的核心思想是把功能模块代码与系统中可能出现错误的处理代码分离开来,以此来达到使我们的代码组织起来更美观、逻辑上更清晰,并且同时从根本上来提高我们软件系统长时间稳定运行的可靠性。

三、c++ 异常处理机制

C++ 异常处理涉及到三个关键字:trycatchthrow

throw: 当问题出现时,程序会抛出一个异常。这是通过使用 throw 关键字来完成的。
catch: 在您想要处理问题的地方,通过异常处理程序捕获异常。catch 关键字用于捕获异常。
try: try 块中的代码标识将被激活的特定异常。它后面通常跟着一个或多个 catch 块。

#include <iostream>
using namespace std;
//抛出一个异常时 
double division(int a, int b)
{
   if( b == 0 )
   {
      //throw了一个exception对象
      throw "Division by zero condition!";
   }
   return (a/b);
}
 
int main ()
{
   int x = 50;
   int y = 0;
   double z = 0;
 //进行异常的捕获
   try {
       z = division(x, y);
       cout << z << endl;
   }catch (const char* msg) {
       cerr << msg << endl; //打印异常信息
   }
 
   return 0;
}

四、c 异常处理机制

  • 直接终止程序(自杀)

常见exit()函数

  • 返回一个错误的值,附加错误码

printf("文件打开失败,错误码:%d\n",errno);

  • 基于goto语句的异常处理
    goto语句是C语言中使用最为灵活的一条语句,直接对应一条“无条件直接跳转的机器指令”,goto语句有非常多的用途或优点,例如,它特别适合于在编写系统程序中被使用,它能使编写出来的代码非常简练,在linux kernel源码也可以看到goto关键字。

注:即使在C++中也保留了goto关键字,但是一般不建议在应用程序中使用,因为goto语句能破坏程序的结构化设计,使代码难于测试,且包含大量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);
}
  • setjmp()函数与longjmp()函数
  1. 首先设置一个跳转点(setjmp() 函数可以实现这一功能)
  2. 然后在其后的代码中任意地方调用 longjmp() 跳转回这个跳转点上,以此来实现当发生异常时,转到处理异常的程序上。

setjmp() 为跳转返回保存现场并为异常提供处理程序,longjmp() 则进行跳转(抛出异常),setjmp() 与 longjmp() 可以在函数间进行跳转,这就像一个全局的 goto 语句,可以跨函数跳转。

#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;
}

setjmp函数用于保存程序的运行时的堆栈环境,接下来的其它地方,你可以通过调用longjmp函数来恢复先前被保存的程序堆栈环境。当 setjmp和longjmp组合一起使用时,它们能提供一种在程序中实现“非本地局部跳转”("non-local goto")的机制。并且这种机制常常被用于来实现,把程序的控制流传递到错误处理模块之中;或者程序中不采用正常的返回(return)语句,或函数的正常调用等方法,而使程序能被恢复到先前的一个调用例程(也即函数)中。

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 计算机系统漫游 代码从文本到可执行文件的过程(c语言示例):预处理阶段,处理 #inlcude , #defin...
    willdimagine阅读 3,641评论 0 5
  • 我们今天说说一种典型的实现C语言异常处理的方法,即以setjmp()函数和longjmp()函数实现的异常...
    Leon_Geo阅读 446评论 0 2
  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,207评论 0 13
  • 曾梦想仗剑走天涯,看一看世界的繁华。 曾经年少的我们,心里总怀揣着自己远大而负有抱负的梦想,然而在成长多年之后,有...
    打冷水的男孩阅读 228评论 0 1
  • 最是那一抹娇羞,萦绕心头 温柔的你 是否还在嘻戏人间 风抚过 留下一地芳香 温柔的你 是否还在浅声莺语 玉音婉转千...
    雨心田阅读 1,522评论 21 29