前言:

像如java这样的面相对象语言,异常处理机制让其代码更具健壮性,可以代码捕获到如算术异常,空指针异常等,俘获并能够在预知情况下进行相应处理。那么对于C而言,是否能实现其功能?

简要分析:

Linux有对线程或者进程退出时有一种信号量机制,而默认情况下,这种signal是系统自己处理的,而最统一的处理方式是exit,而至于什么原因退出这个完全取决于什么样的信号。至于linux下的这些signal多少,哪个对应什么情况自行查阅资料。Linux_c 的实现将通过宏来实现。

直接粗暴上代码吧:

exception.h

#ifndef EXCEPTION_H_
#define EXCEPTION_H_#include <setjmp.h>
#include <signal.h>/* MANPROCSIGnals. */
#define MANPROCSIG_HUP  1 /* Hangup (POSIX). */
#define MANPROCSIG_INT  2 /* Interrupt (ANSI). */
#define MANPROCSIG_QUIT  3 /* Quit (POSIX). */
#define MANPROCSIG_ILL  4 /* Illegal instruction (ANSI). */
#define MANPROCSIG_TRAP  5 /* Trace trap (POSIX). */
#define MANPROCSIG_ABRT  6 /* Abort (ANSI). */
#define MANPROCSIG_IOT  6 /* IOT trap (4.2 BSD). */
#define MANPROCSIG_BUS  7 /* BUS error (4.2 BSD). */
#define MANPROCSIG_FPE  8 /* Floating-point exception (ANSI). */
#define MANPROCSIG_KILL  9 /* Kill, unblockable (POSIX). */
#define MANPROCSIG_USR1  10 /* User-defined MANPROCSIG_nal 1 (POSIX). */
#define MANPROCSIG_SEGV  11 /* Segmentation violation (ANSI). */
#define MANPROCSIG_USR2  12 /* User-defined MANPROCSIG_nal 2 (POSIX). */
#define MANPROCSIG_PIPE  13 /* Broken pipe (POSIX). */
#define MANPROCSIG_ALRM  14 /* Alarm clock (POSIX). */
#define MANPROCSIG_TERM  15 /* Termination (ANSI). */
#define MANPROCSIG_STKFLT 16 /* Stack fault. */
#define MANPROCSIG_CLD  MANPROCSIG_CHLD /* Same as MANPROCSIG_CHLD (System V). */
#define MANPROCSIG_CHLD  17 /* Child status has changed (POSIX). */
#define MANPROCSIG_CONT  18 /* Continue (POSIX). */
#define MANPROCSIG_STOP  19 /* Stop, unblockable (POSIX). */
#define MANPROCSIG_TSTP  20 /* Keyboard stop (POSIX). */
#define MANPROCSIG_TTIN  21 /* Background read from tty (POSIX). */
#define MANPROCSIG_TTOU  22 /* Background write to tty (POSIX). */
#define MANPROCSIG_URG  23 /* Urgent condition on socket (4.2 BSD). */
#define MANPROCSIG_XCPU  24 /* CPU limit exceeded (4.2 BSD). */
#define MANPROCSIG_XFSZ  25 /* File size limit exceeded (4.2 BSD). */
#define MANPROCSIG_VTALRM 26 /* Virtual alarm clock (4.2 BSD). */
#define MANPROCSIG_PROF  27 /* Profiling alarm clock (4.2 BSD). */
#define MANPROCSIG_WINCH 28 /* Window size change (4.3 BSD, Sun). */
#define MANPROCSIG_POLL  MANPROCSIG_IO /* Pollable event occurred (System V). */
#define MANPROCSIG_IO  29 /* I/O now possible (4.2 BSD). */
#define MANPROCSIG_PWR  30 /* Power failure restart (System V). */
#define MANPROCSIG_SYS  31 /* Bad system call. */
#define MANPROCSIG_UNUSED 31#define T Exception_t
typedef struct Exception_t{char *reason;
}Exception_t;typedef struct Exception_frame{struct Exception_frame *prev;jmp_buf env;const char *file;int line;const T* exception;
}Exception_frame;extern Exception_frame *Exception_stack;enum{EXCEPTION_ENTERED=0,EXCEPTION_RAISED,EXCEPTION_HANDLED,EXCEPTION_FINALIZED
};/* Manage all process signal,and automanage signal by process cause exit directoryly,*/
#define ManProcAllSig \int sum = 31; \while(sum){ \signal(sum,handle_proc_sig); \sum--; \
}/*Throw a exception*/
#define throw(e) exception_raise(&(e),__FILE__,__LINE__)#define rethrow exception_raise(exception_frame.exception, \exception_frame.file,exception_frame.line)void handle_proc_sig(int signo);void abort_without_exception(const Exception_t *e,const char *file,int line);void exception_raise(const T *e,const char *file,int line);#define try do{ \volatile int exception_flag; \Exception_frame exception_frame; \exception_frame.prev = Exception_stack; \Exception_stack = &exception_frame; \ManProcAllSig \exception_flag = setjmp(exception_frame.env); \if (exception_flag == EXCEPTION_ENTERED) \{#define catch(e) \if(exception_flag == EXCEPTION_ENTERED) \Exception_stack = Exception_stack->prev; \}else if(exception_flag == e){ \exception_flag = EXCEPTION_HANDLED;#define try_return \switch(Exception_stack = Exception_stack->prev,0) \default: return#define catch_else \if(exception_flag == EXCEPTION_ENTERED) \Exception_stack = Exception_stack->prev; \}else if(exception_flag != EXCEPTION_HANDLED){ \exception_flag = EXCEPTION_HANDLED;#define end_try \if(exception_flag == EXCEPTION_ENTERED) \Exception_stack = Exception_stack->prev; \} \if (exception_flag == EXCEPTION_RAISED) \exception_raise(exception_frame.exception, \exception_frame.file,exception_frame.line); \}while(0)#define finally \if(exception_flag == EXCEPTION_ENTERED) \Exception_stack = Exception_stack->prev; \}{ \if(exception_flag == EXCEPTION_ENTERED) \exception_flag = EXCEPTION_FINALIZED;#undef T
#endif /* EXCEPTION_H_ */

exception.c

#include "exception.h"
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>Exception_frame *Exception_stack = NULL;void exception_raise(const Exception_t *e,const char *file,int line)
{Exception_frame *p = Exception_stack;assert(e);if(p == NULL){abort_without_exception(e,file,line);}p->exception = e;p->file = file;p->line = line;Exception_stack = Exception_stack->prev;longjmp(p->env,EXCEPTION_RAISED);
}void abort_without_exception(const Exception_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();
}void handle_proc_sig(int signo)
{if( signo == MANPROCSIG_HUP )printf(" Hangup (POSIX). \r\n");else if( signo == MANPROCSIG_INT )printf(" Interrupt (ANSI). \r\n");else if( signo == MANPROCSIG_QUIT )printf(" Quit (POSIX). \r\n");else if( signo == MANPROCSIG_ILL )printf(" Illegal instruction (ANSI). \r\n");else if( signo == MANPROCSIG_TRAP )printf(" Trace trap (POSIX). \r\n");else if( signo == MANPROCSIG_ABRT )printf(" Abort (ANSI). \r\n");else if( signo == MANPROCSIG_IOT )printf(" IOT trap (4.2 BSD). \r\n");else if( signo == MANPROCSIG_BUS )printf(" BUS error (4.2 BSD). \r\n");else if( signo == MANPROCSIG_FPE )printf(" Floating-point exception (ANSI). \r\n");else if( signo == MANPROCSIG_KILL )printf(" Kill, unblockable (POSIX). \r\n");else if( signo == MANPROCSIG_USR1 )printf(" User-defined signal if( signo == (POSIX). \r\n");else if( signo == MANPROCSIG_SEGV )printf(" Segmentation violation (ANSI). \r\n");else if( signo == MANPROCSIG_USR2 )printf(" User-defined signal 2 (POSIX). \r\n");else if( signo == MANPROCSIG_PIPE )printf(" Broken pipe (POSIX). \r\n");else if( signo == MANPROCSIG_ALRM )printf(" Alarm clock (POSIX). \r\n");else if( signo == MANPROCSIG_TERM )printf(" Termination (ANSI). \r\n");else if( signo == MANPROCSIG_STKFLT )printf(" Stack fault. \r\n");else if( signo == MANPROCSIG_CLD )printf(" Same as SIGCHLD (System V). \r\n");else if( signo == MANPROCSIG_CHLD )printf(" Child status has changed (POSIX). \r\n");else if( signo == MANPROCSIG_CONT )printf(" Continue (POSIX). \r\n");else if( signo == MANPROCSIG_STOP )printf(" Stop, unblockable (POSIX). \r\n");else if( signo == MANPROCSIG_TSTP )printf(" Keyboard stop (POSIX). \r\n");else if( signo == MANPROCSIG_TTIN )printf(" Background read from tty (POSIX). \r\n");else if( signo == MANPROCSIG_TTOU )printf(" Background write to tty (POSIX). \r\n");else if( signo == MANPROCSIG_URG )printf(" Urgent condition on socket (4.2 BSD). \r\n");else if( signo == MANPROCSIG_XCPU )printf(" CPU limit exceeded (4.2 BSD). \r\n");else if( signo == MANPROCSIG_XFSZ )printf(" File size limit exceeded (4.2 BSD). \r\n");else if( signo == MANPROCSIG_VTALRM )printf(" Virtual alarm clock (4.2 BSD). \r\n");else if( signo == MANPROCSIG_PROF )printf(" Profiling alarm clock (4.2 BSD). \r\n");else if( signo == MANPROCSIG_WINCH )printf(" Window size change (4.3 BSD, Sun). \r\n");else if( signo == MANPROCSIG_POLL )printf(" Pollable event occurred (System V). \r\n");else if( signo == MANPROCSIG_IO )printf(" I/O now possible (4.2 BSD). \r\n");else if( signo == MANPROCSIG_PWR )printf(" Power failure restart (System V). \r\n");else if( signo == MANPROCSIG_SYS)printf(" Bad system call. \r\n");else if( signo == MANPROCSIG_UNUSED)printf(" Unknow erroe. \r\n");Exception_frame *p = Exception_stack;Exception_stack = Exception_stack->prev;longjmp(p->env,signo);// exit(0);//exit process
}

测试:test.c

#include <stdio.h>
#include "exception.h"void test()
{char *a=NULL;*a=1;
}int main()
{try{test();            //SimulateNULLpointerexception!!}catch(MANPROCSIG_SEGV) //Catchtheexception{printf("NULLpointer!!\r\n");}catch_else{printf("UnknowError!!\r\n");}finally{printf("DONE\r\n");}end_try;return 0;
}

linux c 实现try catch异常捕获相关推荐

  1. try catch异常捕获

    这次我们介绍try catch异常捕获.下面是try catch的语法. thy catch 的作用就是异常捕获,在一些会报错的地方时的时候才会用到. 例如这个代码,当我们在控制器时输入的不是数字而是 ...

  2. java报错空指针异常_springboot全局异常捕获,真香

    全局异常捕获 什么是异常?程序在启动或者运行时没有按照预期的执行,在执行途中发生某种未知的错误,导致程序非正常停止或者报错. 在我们的程序中,肯定会伴随着很多的异常,启动时:空对象.找不到数据库.用户 ...

  3. mfc try catch 捕获并显示_你的异常捕获够优雅不?求你别只会try{...} catch{...}了

    文章来源 | cnblogs.com/jurendage/p/11255197.html 作者 | 巨人大哥 软件开发过程中,不可避免的是需要处理各种异常,就我自己来说,至少有一半以上的时间都是在处理 ...

  4. 异常捕获try...catch... c#

    异常捕获try-catch- c# 基本捕获 try{可能会出错的代码}catch (Exception){如果出错了要执行的代码} 参考代码 using System; using System.C ...

  5. Try Catch C++ 异常捕获

    Try Catch C++ 异常捕获 参考文章: (1)Try Catch C++ 异常捕获 (2)https://www.cnblogs.com/0523jy/p/11367831.html 备忘一 ...

  6. swift 异常捕获try catch的使用

    swift 异常捕获try catch的使用 参考文章: (1)swift 异常捕获try catch的使用 (2)https://www.cnblogs.com/LL--Blog/p/5701457 ...

  7. 简单介绍Go语言错误处理异常捕获+异常抛出

    这篇文章主要介绍了Go语言错误处理异常捕获和异常抛出,Go语言的作者认为java等语言的错误处理底层实现较为复杂,就实现了函数可以返回错误类型以及简单的异常捕获,虽然简单但是也非常精妙,大大的提高了运 ...

  8. 用c实现跨平台异常捕获机制

    为什么80%的码农都做不了架构师?>>>    TBOX封装了一套跨平台的异常捕获实现,来模拟windows的seh异常处理功能,而且是线程安全的. 在linux/mac下的实现 使 ...

  9. 【Flutter】Future 异步编程 ( 简介 | then 方法 | 异常捕获 | async、await 关键字 | whenComplete 方法 | timeout 方法 )

    文章目录 一.Future 简介 二.Future.then 使用 三.Future 异常捕获 四.Dart 练习网站 五.async.await 关键字 六.whenComplete 方法 七.ti ...

最新文章

  1. jquery 移除border_jQuery - 删除元素
  2. SDK 和 API 的区别是什么
  3. 内网使用ohmyzsh
  4. requests不容易注意到的细节收集~
  5. Android Application 之 allowBackup 属性浅析
  6. 激励和设定可实现的目标是任何学习成功的关键。
  7. 11g rac生产环境异机恢复报错RMAN-6013
  8. 描述符演练-02-逻辑疏理-类的装饰器
  9. 聊聊传说中的散列哈希Hash算法,以及Java中的HashTable,HashMap,HashSet,ConcurrentHashMap......
  10. php 手动搭建环境
  11. 万达9.3亿美元并购北欧最大院线 全球市场份额逼近20%
  12. linux 索引,Linux学习笔记-索引类命令
  13. [LeetCode] Three Sum题解
  14. Mujoco基本情况介绍
  15. css鼠标经过改变盒子,鼠标经过盒子出现边框(伪元素,定位,css3盒子模型)...
  16. 天下没有不会这么回事!不会就学——北漂18年(28)
  17. 如何优雅地跟老板请假?
  18. STM32单片机:定时器TIM输出PWM波
  19. 【计算机网络】(一)走进网络
  20. C语言——蔡勒(Zeller)公式:快速将任意日期转换为星期数

热门文章

  1. 浅谈工程师的调试法宝(5) -JScope的应用_MCU
  2. HDU 2243 考研路茫茫——单词情结(自动机)
  3. 专访东软杨纪文:深入业务做好移动安全防护
  4. LoadRunner测试问题及解决方法总结
  5. env export set 作用
  6. ie6下js更新元素display:block后,仍然不显示的hack办法
  7. mysql asyn 示例
  8. 非常漂亮的Flash纯脚本生成饼图
  9. 向 Internet Explorer 添加 Google 搜索
  10. java 读写文件[多种方法]