返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C语言异常处理机制案例讲解
  • 378
分享到

C语言异常处理机制案例讲解

2024-04-02 19:04:59 378人浏览 八月长安
摘要

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

异常处理机制:setjmp()函数与longjmp()函数

  C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数的特性来实现异常。
所以,异常的处理过程可以描述为这样:
首先设置一个跳转点(setjmp() 函数可以实现这一功能),然后在其后的代码中任意地方调用 longjmp() 跳转回这个跳转点上,以此来实现当发生异常时,转到处理异常的程序上,在其后的介绍中将介绍如何实现。
setjmp() 为跳转返回保存现场并为异常提供处理程序,longjmp() 则进行跳转(抛出异常),setjmp() 与 longjmp() 可以在函数间进行跳转,这就像一个全局的 Goto 语句,可以跨函数跳转。
举个例子,程序在 main() 函数内使用 setjmp() 设置跳转,并调用另一函数A,函数A内调用B,B抛出异常(调用longjmp() 函数),则程序直接跳回到 main() 函数内使用 setjmp() 的地方返回,并且返回一个值。

-------------------------------------------------------------------------------------------------------------------------

jmp_buf 异常结构

使用 setjmp() 及 longjmp() 函数前,需要先认识一下 jmp_buf 异常结构。jmp_buf 将使用在 setjmp() 函数中,用于保存当前程序现场(保存当前需要用到的寄存器的值),jmp_buf 结构在 setjmp.h 文件内声明:


typedef struct
{
unsigned j_sp; // 堆栈指针寄存器
unsigned j_ss; // 堆栈段
unsigned j_flag; // 标志寄存器
unsigned j_cs; // 代码段
unsigned j_ip; // 指令指针寄存器
unsigned j_bp; // 基址指针
unsigned j_di; // 目的指针
unsigned j_es; // 附加段
unsigned j_si; // 源变址
unsigned j_ds; // 数据段
} jmp_buf;

jmp_buf 结构存放了程序当前寄存器的值,以确保使用 longjmp() 后可以跳回到该执行点上继续执行。

-------------------------------------------------------------------------------------------------------------------------

  setjmp() 与 longjmp() 函数详细说明

setjmp() 与 longjmp() 函数原型如下:

  void _Cdecl longjmp(jmp_buf jmpb, int retval);

  int _Cdecl setjmp(jmp_buf jmpb);

_Cdecl 声明函数的参数使用标准C的进栈方式(由右向左)压栈,_Cdecl 是C语言的一种调用约定,除此以外,PASCAL 也是调用约定之一。C标准调用约定(_Cdecl)所声明的函数不自动清除堆栈,这一事务由调用者自行负责——这也是C可以支持不固定个数的参数的原因。此外,这一调用约定将在函数名前添加一个下划线字符,如某一函数声明为:

int cdecl DoSomething(void);

编译时将自动为 DoSomething 加上下划线前缀,即函数名变为: _DoSomething。

setjmp() 与 longjmp() 函数都使用了 jmp_buf 结构作为形参,它们的调用关系是这样的:

首先调用 setjmp() 函数来初始化 jmp_buf 结构变量 jmpb,将当前CPU中的大部分影响到程序执行的寄存器的值存入 jmpb,为 longjmp() 函数提供跳转,setjmp() 函数是一个有趣的函数,它能返回两次,它应该是所有库函数中唯一一个能返回两次的函数,第一次是初始化时,返回零,第二次遇到 longjmp() 函数调用后,longjmp() 函数使 setjmp() 函数发生第二次返回,返回值由 longjmp() 的第二个参数给出(整型,这时不应该再返回零)。

在使用 setjmp() 初始化 jmpb 后,可以其后的程序中任意地方使用 longjmp() 函数跳转会 setjmp() 函数的位置,longjmp() 的第一个参数便是 setjmp() 初始化的 jmpb,若想跳转回刚才设置的 setjmp() 处,则 longjmp() 函数的第一个参数是 setjmp() 所初始化的 jmpb 这个异常,这也说明一件事,即 jmpb 这个异常,一般需要定义为全局变量,否则,若是局部变量,当跨函数调用时就几乎无法使用(除非每次遇到函数调用都将 jmpb 以参数传递,然而明显地,是不值得这样做的);longjmp() 函数的第二个参数是传给 setjmp() 的第二次返回值,这在介绍 setjmp() 函数时已经介绍过。

异常处理过程

先来对比(参考)一下 c++ 的异常处理,C++ 在语言层上便添加了异常处理机制,使用 try 块来包含那些可能出现错误的代码,你可以在 try 块代码中抛出异常,C++ 使用 throw 来抛出异常。抛出异常后,将转到异常处理程序中执行,C++ 使用 catch 块来包含那些处理异常的代码,catch 块可以接收不同类型的异常。需要说明的是,throw 一般不在 try 块内的代码中抛出异常,try 块内的代码调用了别的函数,如函数A,函数A 又调用了函数 B,throw 可以在函数B中抛出异常,或者更深的函数调用层,无论如何,只要有异常抛出,程序将转到 catch 处执行。

C中如何实现,或者明确地说是模拟这一功能?

下面介绍的是一些简单的方法。

现在假设 longjmp() 第二个值为1,即 setjmp() 第二次将返回1。我们使用一组简单的宏来替代 setjmp() 和 longjmp() 以便使用:

首先定义一个全局的异常:

jmp_buf Jump_Buffer;

因为 setjmp() 第一次调用初始化后返回0,第二次返回非0,可以这样定义一个宏使得它功能接近于 C++ 的 try。

#define try if(!setjmp(Jump_Buffer))

当 setjmp() 函数第一次0 时,取非为真,则执行 try 块内的代码,如:

try{

Test();

}

当因为调用 longjmp() 抛出异常而导致 setjmp() 第二次返回时(程序将会转到 setjmp() 函数处返回,这时,这时应该执行的是异常处理代码。longjmp() 使 setjmp() 函数返回非0,if(!setjmp(JumpBuffer)) 中将值取非则为假,是以,异常处理放在其后应该使用一个 else:

#define catch else

如此看起来便跟 C++ 相似了,setjmp() 函数的第二次返回导致 if() 中表达式值为假,刚好使 catch 块得以执行,如:

try{

Test();

}catch{

puts("Error");

}

实现如 C++ 的 throw 语句,事实上以宏替换 longjmp(jmp_buf, int) 的调用:

#define throw longjmp(Jump_Buffer, 1)

下面的例程解释如何使用这些宏:
-------------------------------------------------------------------------------------------------------------------------


#include"stdio.h"
#include"coNIO.h"
#include"setjmp.h"
jmp_buf Jump_Buffer;
#define try if(!setjmp(Jump_Buffer))
#define catch else
#define throw longjmp(Jump_Buffer,1)
int Test(int T)
{
    if(T>100)
        throw;
    else
          puts("OK.");
    return 0;
}
int Test_T(int T)
{
    Test(T);
    return 0;
}
int main()
{
    int T;
    try{
          puts("Input a value:");
          scanf("%d",&T);
          T++;
          Test_T(T);
      } catch{
          puts("Input Error!");
      }
    getch();
    return 0;
}

到此这篇关于C语言异常处理机制案例讲解的文章就介绍到这了,更多相关C语言异常处理机制内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

--结束END--

本文标题: C语言异常处理机制案例讲解

本文链接: https://lsjlt.com/news/129717.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • C语言异常处理机制案例讲解
    异常处理机制:setjmp()函数与longjmp()函数   C标准库提供两个特殊的函数:setjmp() 及 longjmp(),这两个函数是结构化异常的基础,正是利用这两个函数...
    99+
    2024-04-02
  • C语言异常处理机制实例分析
    本篇内容主要讲解“C语言异常处理机制实例分析”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C语言异常处理机制实例分析”吧!异常处理机制:setjmp()函数与l...
    99+
    2024-04-02
  • C语言异常处理机制的示例分析
    这篇文章将为大家详细讲解有关C语言异常处理机制的示例分析,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。异常处理机制:setjmp()函数与longjmp()函数  C标准库提供两个特殊的函数:setjmp...
    99+
    2023-06-20
  • Go语言异常处理案例解析
    异常处理 程序运行时,发生的不被期望的事件,它阻止了程序按照程序员的预期正常执行,这就是异常 golang中提供了两种处理异常的方式 一种...
    99+
    2024-04-02
  • C语言异常处理机制的概念是什么
    这篇“C语言异常处理机制的概念是什么”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C语言异常处理机制的概念是什么”文章吧。异...
    99+
    2023-06-17
  • C++ 函数异常处理如何与其他语言的异常处理机制相比较?
    c++++ 函数异常处理采用函数 try-catch 块,抛出的异常立即传播到调用函数中,可通过 catch 块捕获和处理。java 和 python 的异常处理分别使用 try-cat...
    99+
    2024-04-15
    c++ 异常处理 python
  • C语言 socketpair用法案例讲解
    socketpair()函数的声明: #include <sys/types.h> #include <sys/socket.h> int socketp...
    99+
    2024-04-02
  • C++11中异常处理机制详解
    目录一、异常的引入二、C++异常的关键字三、异常的抛出与处理规则四、异常缺陷的处理五、自定义异常体系六、异常规范七、异常安全八、异常的优缺点1.优点2.缺点一、异常的引入 传统的C语...
    99+
    2024-04-02
  • Java 超详细讲解Spring MVC异常处理机制
    目录异常处理机制流程图异常处理的两种方式简单异常处理器SimpleMappingExceptionResolver自定义异常处理步骤本章小结异常处理机制流程图 系统中异常包括两类: ...
    99+
    2024-04-02
  • C++中的异常处理机制介绍
    本篇内容介绍了“C++中的异常处理机制介绍”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!异常处理增强错误恢复能力是提高代码健壮性的最有力的途...
    99+
    2023-06-17
  • Android之OOM异常解决案例讲解
    02-03 08:56:12.411: E/AndroidRuntime(10137): FATAL EXCEPTION: main 02-03 08:56:12.411: E/...
    99+
    2024-04-02
  • Java异常处理机制实例分析
    这篇文章主要介绍“Java异常处理机制实例分析”,在日常操作中,相信很多人在Java异常处理机制实例分析问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Java异常处理机制实例分析”的疑惑有所帮助!接下来,请跟...
    99+
    2023-06-29
  • C#System.TypeInitializationException异常处理方案
    目录C# System.TypeInitializationException 异常处理C#基础--错误和异常异常类捕获异常自定义异常总结C# System.TypeInitiali...
    99+
    2023-02-26
    C#异常 System.TypeInitializationException C#异常处理
  • 【JAVA 异常处理机制】
    文章目录 前言1.java异常处理机制2.try-catch3.finally块4.自动关闭特性5.throw关键字6.throws关键字7.throws的重写规则8.异常分类9.异常API10.自定义异常总结: 前言 在Ja...
    99+
    2023-08-23
    java 开发语言 学习 intellij idea
  • 详解C++中的异常和错误处理机制
    目录什么是异常处理C++中的异常处理机制什么是错误处理C++中的错误处理机制结论什么是异常处理 异常处理是指在程序执行过程中发生异常或错误时,程序能够捕获并处理这些异常或错误的机制。...
    99+
    2023-05-19
    C++异常处理机制 C++异常处理 C++错误处理机制 C++ 错误处理
  • C语言指针引用数组案例讲解
    前言:C语言中指针玩的是什么,是内存,要想学好指针的小伙伴们要先对数据在内存中是怎么玩的做一番了解~       当在...
    99+
    2024-04-02
  • Java异常处理机制深入理解
    目录1.初识异常2.异常的基本用法异常处理流程3.为什么要使用异常?异常应只用于异常的情况4. 异常的种类 4.1 受查异常解决方案:4.2非受查异常5.如何使用异常避免不...
    99+
    2024-04-02
  • Golang中异常处理机制详解
    前言 通常我们需要编写好的错误处理方式,在了避免某些程序员滥用异常,于是Go这里直接把异常这一块给砍掉了,最终还是通过返回值来判断程序的异常情况,毕竟Go可是支持多返回值的语言,比如...
    99+
    2024-04-02
  • Java SpringMVC异常处理机制详解
    目录异常处理的思路测试环境准备异常处理两种方式方式一:简单异常处理器方式二:自定义异常处理器总结异常处理的思路 测试环境准备 首先写一个DemoController控制层的类作为测...
    99+
    2024-04-02
  • Java 详解异常的处理机制
    目录1.异常概述与异常体系结构1.1异常概述1.2运行时异常与编译时异常1.3异常体系结构2.常见异常1.ArrayIndexOutOfBoundsException2.NullPo...
    99+
    2024-04-02
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作