每当我创建一个pthread时,valgrind就会输出内存泄漏,
例如以下代码:
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
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导致问题,虽然我使用手册页作为参考,我该如何解决?
答案 0 :(得分:26)
线程是已分配的资源,您在退出之前没有释放它。你应该致电pthread_join
;这也可以消除你的hackish和不正确的睡眠循环的需要。
有可能即使你解决了这个问题,valgrind仍然会看到“泄漏”,因为POSIX线程的一些实现(我猜你正在使用glibc / NPTL)缓存并重用线程资源而不是完全释放它们。我不确定valgrind是否可以解决这个问题。
答案 1 :(得分:5)
我认为valgrind
分析了程序退出时的状态,这可能是在线程完成执行之前:2微秒可能不足以将"Hello, world!\n"
写入控制台。添加对pthread_join
的调用可以解决此漏洞:
pthread_join(timer1, NULL);
答案 2 :(得分:1)
当我无法调用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;
}
答案 3 :(得分:1)
显示的泄漏与在子线程的本地存储(tls)中分配的DTV(动态线程向量)结构有关。
在主线程中使用pthread_join()
(即产生子线程的线程)将确保修复泄漏。
对于不需要pthread_join()
调用的用例,使用子pthread_t调用pthread_detach
可确保释放内存。
来自pthread_detach
的男人:
pthread_detach()
函数标记线程标识的线程 如超脱。分离的线程终止时,其资源是 在不需要的情况下自动释放回系统 另一个与终止线程连接的线程。
答案 4 :(得分:0)
内存泄漏是由于如果线程在没有取消的情况下保持运行,则不会释放相应的动态分配的内存。使用pthread_cancel()和pthread_cleanup_push(CleanupHandler,NULL)和pthread_cleanup_pop(0)在取消后进行线程清理。