当前位置:编程学习 > C/C++ >>

用C模拟异常

 
/** 
 * @file test_try_catch.c 
 * @Brief  使用形如C++的异常来检测超时  
 * @author email:huangkq1989@gmail.com blog:http://blog.csdn.net/kangquan2008 
 * @version 1.0 
 * @date 2013-10-22 
 */  
#include <stdio.h>  
#include <stdlib.h>  
#include <setjmp.h>  
#include <signal.h>  
#include <time.h>  
  
#define  __WITH_TIME_OUT_IMPOSSIBLE__  
#ifdef __WITH_TIME_OUT_IMPOSSIBLE__  
  
static sigjmp_buf __time_out_jump;  
  
typedef void (* __sigfunc)(int);  
static void __do_time_out(int sig)  
{  
  fprintf(stdout,"time out here\n");  
  siglongjmp(__time_out_jump, 1);  
  
}  
  
static void __time_out_reset(__sigfunc store)  
{  
  alarm(0);  
  signal(SIGALRM, store);  
  
}  
  
#define TIME_OUT_TRY(x) \  
{\  
  // 设置超时处理函数,将调用longjmp,使得能进入else,即catch  
  __sigfunc save = signal(SIGALRM, __do_time_out);\  
  // 保存堆栈,返回值为0时表示不是由longjmp返回,  
  // 否则为调用了longjmp后返回的  
  // 参数 1,是为了保存当前进程的信号屏蔽字  
  if(!sigsetjmp(__time_out_jump, 1)) {\  
    //计时  
    alarm(x);  
  
#define TIME_OUT_CATCH \  
  }\  
  // 由于sigsetjmp返回非0,进入CATCH  
  else {\  
  
#define TIME_OUT_END \  
  } \  
  // 恢复SIGALRM的信号处理函数  
  __time_out_reset(save);\  
}  
  
#define TIME_OUT_RETURN(x)  { __time_out_reset(save); return (x);  }  
#define TIME_OUT_RETUR_VOID { __time_out_reset(save); return ;  }  
  
#endif //__WITH_TIME_OUT_IMPOSSIBLE__  
  
int main()  
{  
  int timeout = 10;  
  TIME_OUT_TRY(timeout) {  
    sleep(11);  
  }  
  TIME_OUT_CATCH{  
    TIME_OUT_RETURN(-1);  
  }  
  TIME_OUT_END;  
  
  return 0;  
}  

 
至于为什么用sigsetjmp而不是setjmp:
如果在信号处理函数中调用异常处理,那么这一信号会加入被屏蔽信号集(信号不排队),当用longjmp退出时,影响了原进程的屏蔽信号集!
 
补充:软件开发 , C语言 ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,