引子:
不管是在c++还是在java中,异常都被认为是一种很优雅的处理错误的机制,而如果想在c语言中使用异常就比较麻烦。但是我们仍然可以使用c语言中强大的setjmp和longjmp函数实现类似于c++的异常处理机制。
有关c语言中setjmp和longjmp的资料可以参考:
C语言中一种更优雅的异常处理机制:http://blog.csdn.net/hello_wyq/archive/2006/06/23/826312.aspx
全面了解setjmp与longjmp的使用:http://blog.csdn.net/hello_wyq/archive/2006/06/16/804040.aspx
基本原理
结合setjmp,将当前的环境变量打包为frame(定义的一个结构名)压到一个异常堆栈(自定义的结构体)中,如果程序段正常运行,将此frame弹出,而如果程序出错,将异常栈的顶部元素弹出,根据这个栈顶元素的frame中保存的环境变量,通过setjmp将环境恢复,然后执行某个错误处理函数,而如果没有相应错误处理函数,重新弹出新的栈顶元素,以跳到更外层的setjmp块进行处理。
主要代码分析
此异常机制的实现大量应用了宏,以实现c++和java中异常处理的语法效果。如何使用见下面的如何使用部分。
try部分,作用见注释:c 代码
-
-
- #define try do{ \
- volatile int except_flag; \
- Except_frame except_frame; \
- except_frame.prev = Except_stack; \
- Except_stack = &except_frame; \
- except_flag = setjmp(except_frame.env); \
- if (except_flag == EXCEPT_ENTERED) \
- {
最重要的部分要数except_raise函数,检查异常是否被处理,如果未被处理,重新从异常栈中弹出新的frame,以跳到更外层的异常处理块。
catch(e)也是宏,检查当前的frame是否和这个catch块中的e对应,如果对应的话,执行下面的部分进行处理。
因为所有except_frame全部放在栈上,因此可以说这个except_stack利用了程序自动产生的stack机制,只要正确地改变Except_stack的值就可以了,不必再考虑分配的except_frame的释放问题,空间的分配释放全由程序自动生成的stack管理。
如何使用
使用这个异常机制的代码,如下
c 代码
- try{
- S;
- }catch(e1){
- S1;
- }catch(e2){
- S2;
- }else_catch{
- S3;
- }end_try;
此相当于c++中的:
- try{
- S;
- }catch(e1){
- S1;
- }catch(e2){
- S2;
- }catch(…){
- S3;
- }
当前实现的异常机制也支持finally语句,因此下面的代码:
c代码
- try{
- S;
- }catch(e1){
- S1;
- }finally{
- S2;
- }end_try;
相当于java中的:
java 代码
- try{
- S;
- }catch(e1except e1){
- S1;
- }finally
- S2;
源代码
文件:exception.h
c 代码
- #ifndef __EXCEPTION_H__
- #define __EXCEPTION_H__
-
- #include <stdio.h></stdio.h>
- #include <setjmp.h></setjmp.h>
- #include <assert.h></assert.h>
-
-
- #define T Except_t
- typedef struct Except_t{
- char *reason;
- }Except_t;
-
- typedef struct Except_frame{
- struct Except_frame *prev;
- jmp_buf env;
- const char *file;
- int line;
- const T* exception;
- }Except_frame;
-
- extern Except_frame *Except_stack;
-
-
- enum {EXCEPT_ENTERED=0,EXCEPT_RAISED,
- EXCEPT_HANDLED,EXCEPT_FINALIZED};
-
- #define throw(e) except_raise(&(e),__FILE__,__LINE__)
-
- #define rethrow except_raise(except_frame.exception,\
- except_frame.file,except_frame.line)
-
- void abort_without_exception(const Except_t *e,const char *file,int line);
-
-
- void except_raise(const T *e,const char *file,int line);
-
-
-
- #define try do{ \
- volatile int except_flag; \
- Except_frame except_frame; \
- except_frame.prev = Except_stack; \
- Except_stack = &except_frame; \
- except_flag = setjmp(except_frame.env); \
- if (except_flag == EXCEPT_ENTERED) \
- {
-
-
-
-
-
- #define catch(e) \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }else if(except_frame.exception == &(e)){ \
- except_flag = EXCEPT_HANDLED;
-
- #define try_return \
- switch(Except_stack = Except_stack->prev,0) \
- default: return
-
- #define catch_else \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }else{ \
- except_flag = EXCEPT_HANDLED;
-
-
- #define end_try \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- } \
- if (except_flag == EXCEPT_RAISED) \
- except_raise(except_frame.exception, \
- except_frame.file,except_frame.line); \
- }while(0)
-
-
- #define finally \
- if(except_flag == EXCEPT_ENTERED) \
- Except_stack = Except_stack->prev; \
- }{ \
- if(except_flag == EXCEPT_ENTERED) \
- except_flag = EXCEPT_FINALIZED;
-
- #undef T
- #endif
文件:exception.c
c 代码
- #include "exception.h"
-
- Except_frame *Except_stack = NULL;
-
- void except_raise(const Except_t *e,const char *file,int line)
- {
- Except_frame *p = Except_stack;
-
- assert(e);
- if(p == NULL){
- abort_without_exception(e,file,line);
- }
- p->exception = e;
- p->file = file;
- p->line = line;
- Except_stack = Except_stack->prev;
- longjmp(p->env,EXCEPT_RAISED);
- }
-
- void abort_without_exception(const Except_t *e,const char *file,int line)
- {
- fprintf(stderr,"Uncaught exception");
- if(e->reason)
- fprintf(stderr," %s",e->reason);
- else
- fprintf(stderr," at 0x%p",e);
-
- if (file && line > 0)
- fprintf(stderr, "raised at %s:%d\n",file,line);
- fprintf(stderr,"aborting...\n");
- fflush(stderr);
- abort();
- }
参考资料:<o:p></o:p>
《c语言接口与实现》 David R Hanson<o:p></o:p>
分享到:
相关推荐
此外,还介绍了异常处理机制的不同,Java使用try-catch语句来捕获异常,而C语言使用return语句将异常信息返回给调用者。 在方法方面,详细介绍了JNI接口的定义、C语言编写本地方法以及Java代码调用本地方法的步骤。...
增加异常处理机制:Entry(),Leave(),Throw();这个略微自豪的功能。 建立了调试机制:Trap 指令。这也是一些不错的机制。 增加对宽字符的支持,并实现中文标志符编程. 保证能够实现自我编译(四次递归编译) 在 tcc 环境下...
本文针对嵌入式C语言的编程特点,设计了一种基于堆栈模式的错误追踪机制,并论述了其具体实现方法,包括错误代码定义、错误处理堆栈设计及错误异常的描述方法,给出了详细代码。本方法已经在多个实际嵌入式产品开发中...
本文针对嵌入式C语言的编程特点,设计了一种基于堆栈模式的错误追踪机制,并论述了其具体实现方法,包括错误代码定义、错误处理堆栈设计及错误异常的描述方法,给出了详细代码。本方法已经在多个实际嵌入式产品开发...
Java的强类型机制、异常处理、废料的自动收集等是Java程 序健壮性的重要保证。对指针的丢弃是Java的明智选择。Java的安全检查机制使得Java 更具健壮性。 5、Java语言是安全的。Java通常被用在网络环境中,为此,Java...
4.3.1 缺页异常处理程序 79 4.3.2 请求调页 81 4.3.3 写时复制 83 4.4 物理内存的分配与回收 83 4.4.1 伙伴算法 85 4.4.2 物理页面的分配 86 4.4.3 物理页面的回收 88 4.4.4 slab分配模式 89 4.4.5 内核空间非连续...
6.3.3 MFC中的异常处理 255 6.4 处理内存分配错误 256 6.5 函数重载 257 6.5.1 函数重载的概念 258 6.5.2 引用类型和重载选择 260 6.5.3 何时重载函数 260 6.6 函数模板 261 6.7 使用decltype操作符 263 ...
第11章讨论异常处理,即Java的健壮机制,它用于处理调试好的程序可能出现的意外的情 况。异常提供了一种将正常的处理代码与错误处理代码分开的有效手段。当然,即使程序包含 处理所有异常情况的功能,依然有可能...
第17章 异常处理 17.1C语言的出错处理 17.2抛出异常 17.3异常捕获 17.3.1try块 17.3.2异常处理器 17.3.3异常规格说明 17.3.4更好的异常规格说明 17.3.5捕获所有异常 17.3.6异常的重新抛出 17.3.7未被捕获的异常 17.4...
C++是对C语言的扩充,扩充的绝大部分来自著名语言中的最佳特性:从SIMULA 67中吸取了类,从ALGOL 68中吸取了运算符一名多用、引用和在分程序中任何地方说明变量,综合了Ada的类属和 Clu的模块特点,从BCPL中吸取异常...
查的重点主要有:java基本语法,多线程,异常处理,抽象类,匿名类,接口,MVC架构 ,设计模式,Servlet,Struts,Spring,J2EE。以下是我遇见过的面试问题: 1)transient和volatile是java关键字吗?(瞬联) 2)...
第一章:数据结构和算法 1.1 解压序列赋值给多个变量 1.2 解压可迭代对象赋值给多个变量 1.3 保留最后N个元素 1.4 查找最大或最小的N个元素 ... 15.20 处理C语言中的可迭代对象 15.21 诊断分析代码错误
50.JAVA语言如何进行异常处理,关键字:thorws,throw,try,catch,finally 51.Object类(或者其子类)的finalize()方法在什么情况下被调用? 52.一个“.java”原文件中是否可以包括多个类(不是内部类)? 53.掌握...
自己动手写操作系统在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用C语言和汇编语言编写出一个具备操作系统基本功能的操作系统框架。本书不同于其他的理论型书籍,而是提供给读者一个动手...
本书在详细分析操作系统原理的基础上,用丰富的实例代码,一步一步地指导读者用C语言和汇编语言编写出一个具备操作系统基本功能的操作系统框架。本书不同于其他的理论型书籍,而是提供给读者一个动手实践的路线图。...
1. 4 Linux内核源代码中的C语言代码 1.5 Linux内核源代码中的汇编语言代码 第2章 存储管理 2.1 Linux内存管理的基本框架 2.2 地址映射的全过程 2.3 几个重要的数据结构和函数 2.4 越界访问 2.5 用户...
示例描述:本章学习Java的异常处理。 demoException_1.java 异常示例1 demoException_2.java 异常示例2 demoException_3.java 异常示例3 demoException_4.java 异常示例4 demoException_5.java 异常示例5 ...
本教程共分为5个部分,第一部分是C语言提高部分,第二部分为C++基础部分,第三部分为C++进阶部分,第四部分为C、C++及数据结构基础部分,第五部分为C_C++与设计模式基础,内容非常详细. 第一部分 C语言提高部分目录...
Firebird还实现了域,字段级别的约束,视图,异常,规则和权限管理,更多的详细信息,请参考Firebird发布通知和参考手册。 硬件需求: Firebird可以工作最常见的硬件环境中,甚至非常差的硬件中,也能很好的工作,...