即使状态分离,pthread中的内存泄漏

时间:2019-07-13 04:58:39

标签: linux multithreading memory-leaks pthreads valgrind

我正在学习pthreads编程。

我了解到线程有两种状态: 1.可加入 2.可拆卸

在Joinable的情况下,我们需要调用pthread_join释放资源(堆栈),而在分离的情况下,不需要调用pthread_join,并且资源将在线程退出时释放。

我编写了一个示例程序来观察行为

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>

void *threadFn(void *arg)
{

 pthread_detach(pthread_self());
 sleep(1);
 printf("Thread Fn\n");
 pthread_exit(NULL);
}

int main(int argc, char *argv[])
{

 pthread_t tid;
 int ret = pthread_create(&tid, NULL, threadFn, NULL);

 if (ret != 0) {
  perror("Thread Creation Error\n");
  exit(1);
 }
 printf("After thread created in Main\n");
 pthread_exit(NULL);
}

当我尝试使用valgrind检查任何内存泄漏时,它给了我272个字节的泄漏。你能告诉我为什么这里发生泄漏吗?

$valgrind --leak-check=full ./app
==38649== 
==38649== HEAP SUMMARY:
==38649==     in use at exit: 272 bytes in 1 blocks
==38649==   total heap usage: 7 allocs, 6 frees, 2,990 bytes allocated
==38649== 
==38649== 272 bytes in 1 blocks are possibly lost in loss record 1 of 1
==38649==    at 0x4C31B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==38649==    by 0x40134A6: allocate_dtv (dl-tls.c:286)
==38649==    by 0x40134A6: _dl_allocate_tls (dl-tls.c:530)
==38649==    by 0x4E44227: allocate_stack (allocatestack.c:627)
==38649==    by 0x4E44227: pthread_create@@GLIBC_2.2.5 (pthread_create.c:644)
==38649==    by 0x108902: main (2.c:18)
==38649== 
==38649== LEAK SUMMARY:
==38649==    definitely lost: 0 bytes in 0 blocks
==38649==    indirectly lost: 0 bytes in 0 blocks
==38649==      possibly lost: 272 bytes in 1 blocks
==38649==    still reachable: 0 bytes in 0 blocks
==38649==         suppressed: 0 bytes in 0 blocks
==38649== 
==38649== For counts of detected and suppressed errors, rerun with: -v
==38649== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

1 个答案:

答案 0 :(得分:1)

您的期望是正确的,一旦调用pthread_exit,主线程就不应有任何泄漏。

但是,您观察到的是您正在使用的实现(可能是glibc)的古怪之处-pthreads库(glibc实现)将最初分配的堆栈重用于线程-像高速缓存一样,以便先前分配的堆栈可以在任何可能的地方重复使用。

Valgrind仅报告其“看到”的内容(已分配但未取消分配的内容)。但这不是真正的泄漏,因此您不必为此担心。

如果“反转”逻辑(主线程作为最后一个线程退出),则不会看到泄漏,因为最初分配的堆栈空间已由主线程正确释放。但是无论如何,这种泄漏都不是真正的泄漏,您可以放心地忽略它。

您还可以设置suppression file,以使Valgrind不会对此抱怨(这是要告知Valgrind“我知道这不是真正的泄漏,因此请不要报告”),例如为:

{
   Pthread_Stack_Leaks_Ignore
   Memcheck:Leak
   fun:calloc
   fun:allocate_dtv
   fun:_dl_allocate_tls
   fun:allocate_stack
   fun:pthread_create*

}