C 工具库2:异常处理
使用setjmp,longjmp实现的C与言异常处理框架。
提供 抛出异常,捕获异常等功能。
exception.h
#ifndef _EXCEPTION_H
#define _EXCEPTION_H
#define except_alloc_failed 1 //内存分配失败
#define except_list_empty 2 //list_pop操作,当list为空触发
//............
#endif
except.h
#ifndef _EXCEPT_H
#define _EXCEPT_H
#include <setjmp.h>
#include <stdio.h>
#include <assert.h>
struct exception_frame
{
struct exception_frame *pre;
jmp_buf jumpbuffer;
int exception;
int line;
const char *file;
};
extern struct exception_frame *exception_stack;
extern void exception_throw(int code,const char *file,int line);
/*一个函数第一次使用TRY前必须定义,如果重复定义会出现不确定的行为
* 主要是为了正确处理在TRY代码内的RETURN
*/
#define FUNCTION_TRY int function_except_stack_count = 0;
#define TRY do{\
++function_except_stack_count;\
struct exception_frame frame;\
frame.pre = exception_stack;\
exception_stack = &frame;\
if((frame.exception = setjmp(frame.jumpbuffer)) == 0)
#define THROW(EXP) exception_throw(EXP,__FILE__,__LINE__)
#define RETHROW exception_throw(frame.exception,frame.file,frame.line)
#define CATCH(EXP) else if(EXP == frame.exception ? frame.exception = 0,1:0)
#define CATCH_ALL else if(frame.exception ? frame.exception = 0,1:0)
#define ENDTRY --function_except_stack_count;\
if(frame.exception){\
exception_throw(frame.exception,frame.file,frame.line);}\
else if(exception_stack){\
exception_stack = exception_stack->pre;\
}\
}while(0);
#define FINALLY
/*根据当前函数中try的处理情况丢弃数量正确的异常栈,再返回*/
#define RETURN(R) do{if(exception_stack){\
while(exception_stack && function_except_stack_count>0){\
function_except_stack_count--;\
exception_stack = exception_stack->pre;\
}\
}\
return R;\
}while(0)
#endif
except.c
#include "except.h"
#include <stdlib.h>
struct exception_frame *exception_stack = 0;
void exception_throw(int code,const char *file,int line)
{
if(exception_stack)
{
exception_stack->exception = code;
exception_stack->file = file;
exception_stack->line = line;
struct exception_frame *frame = exception_stack;
exception_stack = frame->pre;
longjmp(frame->jumpbuffer,code);
}
else
{
printf("unsolved exception %d,file:%s line:%d\n",code,file,line);
}
}
test.c
#include "except.h"
int func1()
{
FUNCTION_TRY
TRY{
TRY{
RETURN(0);
func2();
}
printf("func1 %d\n",function_except_stack_count);
ENDTRY
}
CATCH(1)
{
printf("catch a exception\n");
}
FINALLY
{
printf("func1 %d\n",function_except_stack_count);
RETURN(0);
printf("func1 finally\n");
}
ENDTRY
}
int func2()
{
printf("beginjump\n");
THROW(2);
printf("end of func2\n");
}
int main()
{
FUNCTION_TRY
TRY{
func1();
printf("return\n");
TRY{
func1();
}
CATCH(2)
{
printf("catch a exception 2\n");
TRY{
THROW(2);
}
ENDTRY
}
FINALLY
{
printf("finally\n");
}
ENDTRY
}
CATCH_ALL
{
printf("catch all\n");
}
ENDTRY
return 0;
}