linux c 实现try catch异常捕获
前言:像如java这样的面相对象语言,异常处理机制让其代码更具健壮性,可以代码捕获到如算术异常,空指针异常等,俘获并能够在预知情况下进行相应处理。那么对于C而言,是否能实现其功能?简要分析:Linux有对线程或者进程退出时有一种信号量机制,而默认情况下,这种signal是系统自己处理的,而最统一的处理方式是exit,而至于什么原因退出这个完全取决于什么样的信号。至于linux下的这些s...
·
前言:
像如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;
}
更多推荐
已为社区贡献89条内容
所有评论(0)