为了在C语言环境中抓住异常。。。

c 写的程序经常会有空指针引用,遇到这种情况,程序会被系统强行终止,客户会看到一个该死的对话框,里面写着神秘的诅咒代码。
为了不被使用程序的用户咒骂,应该温和的给予温柔的提示,并保存当前的工作内容,
于是我开发了这个小工具代码,允许你像 Java 一样的抓住异常,这是程序例子:
支持多线程,支持嵌套 try

1234567891011121314151617181920212223242526
#include <stdio.h>
#include <stdlib.h>
#include "exception.h"

int  main ()
{
     try  {

         try  {
              int  * a  =  NULL ;
              * a  =  1 ;
         }  catch ( b )  {
             printf ( "some error 2. %x \n " ,  b );
         }  finally  {
         }

         int  * a  =  NULL ;
         * a  =  1 ;

     }  catch ( a )  {
         printf ( "some error 1. %x \n " ,  a );
     }  finally

     printf ( "over \n " );
     return  0 ;
} 

最新的代码版本
https://github.com/yanmingsohu/c-tool

头文件:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
// J.yanming 2013/7/19 yanming-sohu@sohu.com
// CatfoOD crazy code.
// 如果不需要导出 try 等关键字,则定义 NOT_EXPORT_TRY
// finally 必须出现在 catch 之后!

#ifndef _EXCEPTION_J_
#define _EXCEPTION_J_

#include <setjmp.h>

#define _MAX_EXCEPTION_DEEP_ 255
#define _MAX_THREAD_COUNT_ 255
#define _HAS_EXCEPTION_ 1
#define _NOT_EXCEPTION_ 0

#ifdef __WIN32__
#include <Windows.h>
#define THREAD_ID DWORD
#define GET_CURRENT_THREAD GetCurrentThreadId
typedef  EXCEPTION_POINTERS *  EXCEPTION_INF ;
#else
#ifdef __linux__
#include <pthread.h>
#define THREAD_ID pthread_t
#define GET_CURRENT_THREAD pthread_self
typedef  void *  EXCEPTION_INF ;  // ?
#else
// Other system.
#define THREAD_ID int
#define GET_CURRENT_THREAD i_dont_know
typedef  void *  EXCEPTION_INF ;
#endif  // __linux__
#endif  // __WIN32__


typedef  struct  __THREAD_MARK  {
     EXCEPTION_INF  exception_info ;
     THREAD_ID  thread_id ;
     int  current_exp_mark ;
     jmp_buf  mark [ _MAX_EXCEPTION_DEEP_ ];
}  THREAD_MARK ;


typedef  jmp_buf *  ExceptionMark ;

void  _init_exception ();
void  _exit_exception_deep ();
THREAD_MARK *  _create_exception_deep ();


#define _TRY_ \
_init_exception(); \
THREAD_MARK* ___exp_mark = _create_exception_deep(); \
if (___exp_mark && \
(setjmp(___exp_mark->mark[___exp_mark->current_exp_mark]) == _NOT_EXCEPTION_) ) {

#define _CATCH_(x) \
_exit_exception_deep(___exp_mark); \
} else { \
_exit_exception_deep(___exp_mark); \
EXCEPTION_INF x = ___exp_mark->exception_info;

#define _TEND_ \
}


#ifndef NOT_EXPORT_TRY
     # define  try  _TRY_
     # define  catch  _CATCH_
     # define  finally  _TEND_
#endif

#endif

源文件:

 

// J.yanming 2013/7/19 yanming-sohu@sohu.com
// CatfoOD crazy code.

#include "exception.h"


static  THREAD_MARK  thread_mark [ _MAX_THREAD_COUNT_ ];
static  int  mark_length  =  0 ;
static  int  inited  =  0 ;


static  void  reclaimMemory ()  {
     // 需要同步锁,防止在读取的时候修改了内存顺序
}

static  THREAD_MARK *  findThread ()  {
     THREAD_ID  tid  =  GET_CURRENT_THREAD ();
     THREAD_MARK *  tm  =  NULL ;
     int  i ;

     for  ( i = 0 ;  i < mark_length ;  ++ i )  {
         if  ( thread_mark [ i ]. thread_id  ==  tid )  {
             tm  =  thread_mark  +  i ;
             break ;
         }
     }
     return  tm ;
}

static  THREAD_MARK *  newThread ()  {
     if  ( mark_length  >=  _MAX_THREAD_COUNT_ )  {
         reclaimMemory ();
         if  ( mark_length  >=  _MAX_THREAD_COUNT_ )  {
             return  NULL ;
         }
     }

     THREAD_ID  tid  =  GET_CURRENT_THREAD ();
     THREAD_MARK *  tm  =  & thread_mark [ mark_length ++ ];
     tm -> thread_id  =  tid ;

     return  tm ;
}

static  void  outThread ( THREAD_MARK *  tm )  {
     if  ( tm )  {
         tm -> thread_id  =  0 ;
     }
}

#ifdef __WIN32__
static  long  WINAPI  _ExceptionGlobeFilter ( EXCEPTION_POINTERS *  lParam )  {
     THREAD_MARK *  tm  =  findThread ();
     if  ( tm -> current_exp_mark )  {
         tm -> exception_info  =  lParam ;
         longjmp ( tm -> mark [ tm -> current_exp_mark ],  _HAS_EXCEPTION_ );
     }
     return  1 ;
}
#endif

void  _init_exception ()  {
     if  ( ! inited )  {
#ifdef __WIN32__
         SetUnhandledExceptionFilter ( _ExceptionGlobeFilter );
#endif
         inited  =  1 ;
     }
}

THREAD_MARK *  _create_exception_deep ()  {
     THREAD_MARK *  tm  =  findThread ();
     if  ( ! tm )  tm  =  newThread ();
     if  ( ! tm )  return  NULL ;

     int  deep  =  tm -> current_exp_mark ;
     if  ( deep  >=  _MAX_EXCEPTION_DEEP_ )  {
         return  NULL ;
     }  else  {
         tm -> current_exp_mark ++ ;
     }
     return  tm ;
}

void  _exit_exception_deep ( THREAD_MARK *  tm )  {
     if  ( tm -> current_exp_mark  >  0 )  {
         -- tm -> current_exp_mark ;
     }  else  {
         outThread ( tm );
     }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值