我正在学习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)
答案 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*
}