sigsetjmp siglongjmp使用时要注意内存泄露

来源:互联网 发布:此windows副本不是正版 编辑:程序博客网 时间:2024/05/17 02:06


如果你在sigsetjmp条件内构造了一个对象,那么很容易造成内存泄露,程序的
突然跳转,导致析构函数还没有执行.以下是测试代码

#include <stdio.h>#include <stdlib.h>#include <stdarg.h>#include <string.h>#include <setjmp.h>#include <signal.h>#include <time.h>#include <assert.h>#include <errno.h>#include <unistd.h>#include <fcntl.h>#include <sys/time.h>#include <arpa/inet.h>#include <pthread.h>class A{public:A(){i=0;printf("constructor\n");}~A(){printf("unconstructor\n");}int i;};pthread_t tid_result_manager;jmp_buf jb_result_manager;void sigexit_main(int){printf("主线程接收到了退出信号。\n" );pthread_kill( tid_result_manager,SIGUSR1 );return;}void sigalrm(int s) { printf("sigalrm signal=%d\n",s);    siglongjmp( jb_result_manager, 1 );   //此处返回1 ,继续执行}void sigexit(int s) {printf("sigexit signal=%d\n",s);pthread_t tid = pthread_self();if ( tid == tid_result_manager )        siglongjmp( jb_result_manager, -1 );  //返回-1assert(0);}int icout=0;void *result_manager( void * ){sigset_t set;    int alarm_time = 2;int ret=0;printf("线程启动。\n" );    signal( SIGUSR1, sigexit );    signal( SIGALRM, sigalrm );sigemptyset( &set );sigaddset( &set, SIGUSR1 );    sigaddset( &set, SIGALRM );    pthread_sigmask( SIG_UNBLOCK, &set, NULL );  //不阻止SIGUSR1信号    if ( ( ret = sigsetjmp( jb_result_manager, 1 ) ) != -1 ) {        if ( ret ) {printf("ret=%d,alarm_time=%d\n",ret,alarm_time);pthread_sigmask( SIG_BLOCK, &set, NULL );icout++;if(icout<5){alarm( alarm_time ); }A a;a.i++;printf("cccc a.i=%d\n",a.i);sleep(5);alarm(0);  //取消定时器printf("线程内 ,取消 定时器之后 \n");pthread_sigmask( SIG_UNBLOCK, &set, NULL );  // while ( 1 ) pause(); //让程序等待信号}printf("waiting signal。\n" );while ( 1 ) pause(); //让程序等待信号}printf("线程退出。\n" );return NULL;}int main( int argc, char *argv[] ){   printf("pid=%d",getpid());sigset_t set;sigfillset( &set );sigprocmask( SIG_BLOCK, &set, NULL );   pthread_create( &tid_result_manager, NULL, result_manager, NULL ); signal( SIGINT, sigexit_main );signal( SIGTERM, sigexit_main );signal( SIGQUIT, sigexit_main );sigemptyset( &set );sigaddset( &set, SIGINT );sigaddset( &set, SIGTERM );sigaddset( &set, SIGQUIT );pthread_sigmask( SIG_UNBLOCK, &set, NULL );sleep(5);  pthread_kill( tid_result_manager, SIGALRM );printf("SIGALRM sigal sended\n");pthread_join( tid_result_manager, NULL );printf("program退出。\n" );return 0;}


 


打印结果为
pid=5487线程启动。
waiting signal。
SIGALRM sigal sended
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
sigalrm signal=14
ret=1,alarm_time=2
constructor
cccc a.i=1
线程内 ,取消 定时器之后
unconstructor
waiting signal。
主线程接收到了退出信号。
sigexit signal=10
线程退出。
program退出。


可以很明显的看到析构函数就执行了最后一次,所以使用时一定要小心.尽可能少使用sigsetjmp siglongjmp函数,有个问题,为什么线程内 ,取消 定时器之后能被打印出来?

 

0 0
原创粉丝点击