2014-07-25 38 views
1

我有一个应该启动线程的程序。为了避免退出软件,线程以无限循环运行,并加入线程。这个线程永远不会返回一个值。所以现在我有问题,我调用pthread_cancel valgrind检测到内存泄漏。我怎样才能避免这种内存泄漏?如何通过使用pthread_cancel来避免内存泄漏?

Valgrind的输出:

==5673== 136 bytes in 1 blocks are possibly lost in loss record 4 of 8 
==5673== at 0x4026A68: calloc (vg_replace_malloc.c:566) 
==5673== by 0x40111FB: _dl_allocate_tls (dl-tls.c:300) 
==5673== by 0x404E5A0: [email protected]@GLIBC_2.1 (allocatestack.c:580) 
==5673== by 0x804C44E: start (mythread.c:25) 
==5673== by 0x804D128: main (main.c:10) 

代码:

int main(){ 
    signal(SIGINT,cleanup); 
    signal(SIGQUIT,cleanup); 
    signal(SIGSEGV,cleanup); 
    start(); 
    return 0; 
} 

int start() 
{ 
    pthread_create(&thread_id[0],NULL,&threadhandler,NULL); 
    pthread_join(thread_id[0],NULL); 
    return err; 
} 

void cleanup(){ 
    pthread_cancel(thread_id[0]); 
    exit(0); 
} 

void cleanup_tcp(void *p){ 
} 


void* threadhandler(void *arg) 
{ 
    (void) arg; 
    int status = 0; 
    while(TRUE){ 
     pthread_cleanup_push(cleanup_tcp,NULL); 
     pthread_testcancel(); 
     fprintf(stderr,"Run\n"); 
     pthread_cleanup_pop(0); 
    } 
    return NULL; 
} 
+1

拆卸螺纹(通过调用'pthread_detach()')取消它可以帮助(位)之前。 – alk

回答

1

你已经正确识别使用pthread_cancel()的缺点:由线程清理例程释放也将随之泄露尚未发布任何资源/。就你而言,看起来线程库本身可能已经分配了一些未被释放的内存。

一个更好的方法,国际海事组织,将创建一个机制,通知threadhandler线程,它应该终止。例如

static volatile sig_atomic_t done = 0; 
... 
void cleanup() 
{ 
    done = 1; 
} 

void* threadhandler(void* arg) 
{ 
    while (!done) 
     fprintf(stderr, "Run\n"); 
    return NULL; 
} 
+0

'挥发性'是多余的和有害的。使用一个原子变量就足够了。 – cmaster

+0

@cmaster我不同意。 X/Open规范明确引用了'volatile'限定符:“如果信号不是由于调用abort(),raise(),[CX] [Option Start] kill(),pthread_kill()或sigqueue (),[Option End]如果信号处理程序引用具有静态存储持续时间的任何对象,而不是通过为声明为volatile的sig_atomic_t,...分配值的对象,则行为未定义。此外,“此参考页上描述的功能与ISO C标准一致”。 –

+0

好吧,可能我对X/Open不够了解,我根据C标准的条件来判断,假设'sig_atomic_t'是一个与C标准定义为原子的类型相同的类型。如果是这样的话,那么'volatile'就没用了。但是现在看来,X/Open规范是在C标准定义的原子类型之前编写的,所以现在我想'volatile'确实需要与'sig_atomic_t'结合使用。不过,我会建议使用当前C标准的原子类型。 – cmaster