为什么pthread导致内存泄漏

每当我创建一个pthread时,valgrind就会输出内存泄漏,

例如下面的代码:

#include  #include  #include  void *timer1_function (void *eit){ (void) eit; printf("hello world\n"); pthread_exit(NULL); } int main(void){ pthread_t timer1; pthread_create( &timer1, NULL, timer1_function, NULL); ///////line13 int i=0; for(i=0;i<2;i++){usleep(1);} return 0; } 

valgrind输出

 ==1395== HEAP SUMMARY: ==1395== in use at exit: 136 bytes in 1 blocks ==1395== total heap usage: 6 allocs, 5 frees, 1,134 bytes allocated ==1395== ==1395== 136 bytes in 1 blocks are possibly lost in loss record 1 of 1 ==1395== at 0x402A629: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1395== by 0x4011304: allocate_dtv (dl-tls.c:297) ==1395== by 0x4011AAB: _dl_allocate_tls (dl-tls.c:461) ==1395== by 0x4052470: pthread_create@@GLIBC_2.1 (allocatestack.c:571) ==1395== by 0x8048566: main (test.c:13) ==1395== ==1395== LEAK SUMMARY: ==1395== definitely lost: 0 bytes in 0 blocks ==1395== indirectly lost: 0 bytes in 0 blocks ==1395== possibly lost: 136 bytes in 1 blocks ==1395== still reachable: 0 bytes in 0 blocks ==1395== suppressed: 0 bytes in 0 blocks 

虽然我使用手册页作为参考,为什么pthread_create会导致问题,我该如何解决?

线程是已分配的资源,您在退出之前没有释放它。 你应该调用pthread_join ; 这也可以消除你的hackish和不正确的睡眠循环的需要。

有可能即使你解决了这个问题,valgrind仍会看到“泄漏”,因为POSIX线程的一些实现(我猜你正在使用glibc / NPTL)缓存并重用线程资源而不是完全释放它们。 我不确定valgrind是否可以解决这个问题。

我认为valgrind在程序退出时分析程序的状态,这可能在线程完成执行之前:2微秒可能不足以将"Hello, world!\n"写入控制台。 添加对pthread_join的调用应修复此泄漏:

 pthread_join(timer1, NULL); 

当我没有调用pthread_join时,我看到了类似的结果。

当我调用pthread_join时,Valgrind将指示没有内存错误或泄漏。 我使用pthread_kill查看线程是否仍然存在,然后调用join来清理和释放资源。

 int stop_worker(worker_t *self) { if (self) { // signal the thread to quit // (here using a variable and semaphore) self->thread_quit=TRUE; sem_post(&self->sem); // wait for it to stop // (could use counter, etc. to limit wait) int test=0; while (pthread_kill(self->thread,0) == 0) { MDEBUG(MD_XF_LOGGER,"waiting for thread to exit...\n",test); delay_msec(50); } // even though thread is finished, need to call join // otherwise, it will not release its memory (and valgrind indicates a leak) test=pthread_join(self->thread,NULL); return 0; } return -1; } 

显示的泄漏与在子线程的本地存储(tls)中分配的DTV(动态线程向量)结构有关。

在主线程中使用pthread_join() (即生成子进程的线程)将确保修复泄漏。 对于不需要pthread_join()调用的用例,使用子pthread_t调用pthread_detach可确保释放内存。

来自man for pthread_detach

pthread_detach()函数将线程标识的线程标记为已分离。 当分离的线程终止时,其资源会自动释放回系统,而不需要另一个线程与终止的线程连接。

内存泄漏是由于如果线程在没有取消的情况下保持运行的事实,则不会释放相应的动态分配的内存。 使用pthread_cancel()和pthread_cleanup_push(CleanupHandler,NULL)和pthread_cleanup_pop(0)在取消后进行线程清理。