一直想在C语言中使用像python和C++中的try那样的语句,使程序在出错的时候能不崩溃。通过对linux的信号的编程可以大致实现这个机制。不过还是不好很用的说。
使用到的函数,
signal(), sigsetjmp(),siglongjmp()。
sighandler_t signal(int signum, sighandler_t handler);
signum:是要捕捉的信号,其中SIGKILL和SIGSTOP,是不可以被捕捉和忽略的。
信号列表:
#define SIGHUP 1
#define SIGINT 2
#define SIGQUIT 3
#define SIGILL 4
#define SIGTRAP 5
#define SIGABRT 6
#define SIGEMT 7
#define SIGFPE 8
#define SIGKILL 9
#define SIGBUS 10
#define SIGSEGV 11
#define SIGSYS 12
#define SIGPIPE 13
#define SIGALRM 14
#define SIGTERM 15
#define SIGURG 16
#define SIGSTOP 17
#define SIGTSTP 18
#define SIGCONT 19
#define SIGCHLD 20
#define SIGTTIN 21
#define SIGTTOU 22
#define SIGIO 23
#define SIGXCPU 24
#define SIGXFSZ 25
#define SIGVTALRM 26
#define SIGPROF 27
#define SIGWINCH 28
#define SIGINFO 29
#define SIGUSR1 30
#define SIGUSR2 31
参数:handle信号处理函数指针。有三个特殊的宏可以做为其值。
#define SIG_DFL ((__sighandler_t)0) /* default signal handling */
#define SIG_IGN ((__sighandler_t)1) /* ignore signal */
#define SIG_ERR ((__sighandler_t)-1) /* error return from signal */
int sigsetjmp(sigjmp_buf env, int savesigs);
而在程序其他地方调用siglongjmp()时便会直接跳到这个记号位置,然后还原堆栈,继续程序的执行。
参数env为用来保存目前堆栈环境,一般声明为全局变量
参数savesigs若为非0则代表搁置的信号集合也会一块保存
void siglongjmp(sigjmp_buf env, int val);
跳转到siglongjmp标记的地方。
通过捕捉SIGSEGV信号,实现出现段错误,捕捉到进行别的处理使程序不崩溃的情况。
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <setjmp.h>
#include <pthread.h>
sigjmp_buf my_jmp;
void sigsegv_handle()
{
fprintf(stderr, "%s\n", "call sigsegv_handle!");
siglongjmp(my_jmp, 1); //跳转到sigsetjmp处。
}
void foo()
{
signal(SIGSEGV, sigsegv_handle); //注册信号处理函数。
if(sigsetjmp(my_jmp, 1)) //设置跳转点。
{
fprintf( stderr,"Segmentation fault. Goto log.\n");
goto log; //越过段错误代码段。
}
printf("%s\n", "segv before!");
printf("%s\n", 1); //出现段错误。
printf("%s\n", "segv after!");
printf("log before!\n");
log:
printf("log after!\n");
}
int main(int argc, char const *argv[])
{
foo();
return 0;
}