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


如果你在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 );  //返回-1
	assert(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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值