我在我的程序中使用pthread。它运行良好,但valgrind检测到仍然可达。总是相同的字节:1654,4块。在valgrind中总是可以看到相同的函数。
Valgrind日志:
==29908== Memcheck, a memory error detector
==29908== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==29908== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==29908== Command: ./a.out
==29908== Parent PID: 23902
==29908==
==29908==
==29908== HEAP SUMMARY:
==29908== in use at exit: 1,654 bytes in 4 blocks
==29908== total heap usage: 8 allocs, 4 frees, 2,526 bytes allocated
==29908==
==29908== 36 bytes in 1 blocks are still reachable in loss record 1 of 4
==29908== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==29908== by 0x401F5CE: strdup (strdup.c:42)
==29908== by 0x4019A81: _dl_load_cache_lookup (dl-cache.c:338)
==29908== by 0x400A989: _dl_map_object (dl-load.c:2102)
==29908== by 0x4015D36: dl_open_worker (dl-open.c:513)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x40155F9: _dl_open (dl-open.c:837)
==29908== by 0x49DE860: do_dlopen (dl-libc.c:96)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x49DF982: _dl_catch_error (dl-error-skeleton.c:227)
==29908== by 0x49DE994: dlerror_run (dl-libc.c:46)
==29908== by 0x49DE994: __libc_dlopen_mode (dl-libc.c:195)
==29908== by 0x486E99A: pthread_cancel_init (unwind-forcedunwind.c:53)
==29908==
==29908== 36 bytes in 1 blocks are still reachable in loss record 2 of 4
==29908== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==29908== by 0x400D5A7: _dl_new_object (dl-object.c:196)
==29908== by 0x4006E96: _dl_map_object_from_fd (dl-load.c:997)
==29908== by 0x400A61A: _dl_map_object (dl-load.c:2236)
==29908== by 0x4015D36: dl_open_worker (dl-open.c:513)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x40155F9: _dl_open (dl-open.c:837)
==29908== by 0x49DE860: do_dlopen (dl-libc.c:96)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x49DF982: _dl_catch_error (dl-error-skeleton.c:227)
==29908== by 0x49DE994: dlerror_run (dl-libc.c:46)
==29908== by 0x49DE994: __libc_dlopen_mode (dl-libc.c:195)
==29908== by 0x486E99A: pthread_cancel_init (unwind-forcedunwind.c:53)
==29908==
==29908== 384 bytes in 1 blocks are still reachable in loss record 3 of 4
==29908== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==29908== by 0x401330A: _dl_check_map_versions (dl-version.c:274)
==29908== by 0x40160EC: dl_open_worker (dl-open.c:577)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x40155F9: _dl_open (dl-open.c:837)
==29908== by 0x49DE860: do_dlopen (dl-libc.c:96)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x49DF982: _dl_catch_error (dl-error-skeleton.c:227)
==29908== by 0x49DE994: dlerror_run (dl-libc.c:46)
==29908== by 0x49DE994: __libc_dlopen_mode (dl-libc.c:195)
==29908== by 0x486E99A: pthread_cancel_init (unwind-forcedunwind.c:53)
==29908== by 0x486EBB3: _Unwind_ForcedUnwind (unwind-forcedunwind.c:127)
==29908== by 0x486CF05: __pthread_unwind (unwind.c:121)
==29908==
==29908== 1,198 bytes in 1 blocks are still reachable in loss record 4 of 4
==29908== at 0x483DD99: calloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==29908== by 0x400D273: _dl_new_object (dl-object.c:89)
==29908== by 0x4006E96: _dl_map_object_from_fd (dl-load.c:997)
==29908== by 0x400A61A: _dl_map_object (dl-load.c:2236)
==29908== by 0x4015D36: dl_open_worker (dl-open.c:513)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x40155F9: _dl_open (dl-open.c:837)
==29908== by 0x49DE860: do_dlopen (dl-libc.c:96)
==29908== by 0x49DF8B7: _dl_catch_exception (dl-error-skeleton.c:208)
==29908== by 0x49DF982: _dl_catch_error (dl-error-skeleton.c:227)
==29908== by 0x49DE994: dlerror_run (dl-libc.c:46)
==29908== by 0x49DE994: __libc_dlopen_mode (dl-libc.c:195)
==29908== by 0x486E99A: pthread_cancel_init (unwind-forcedunwind.c:53)
==29908==
==29908== LEAK SUMMARY:
==29908== definitely lost: 0 bytes in 0 blocks
==29908== indirectly lost: 0 bytes in 0 blocks
==29908== possibly lost: 0 bytes in 0 blocks
==29908== still reachable: 1,654 bytes in 4 blocks
==29908== suppressed: 0 bytes in 0 blocks
==29908==
==29908== For lists of detected and suppressed errors, rerun with: -s
==29908== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
如果我将程序限制为1个线程,我永远不会得到任何仍然可达的。如果我把它限制在像2这样低的值,有时会,有时不会。任何高(48)都意味着我几乎总是可以联系到的。
我设法在没有太多代码的情况下重现了这个问题,如下所示。我做错了什么?如果我没有做错什么,它只是一个线程的事情,为什么它仍然是可达的?为什么它是半随机的取决于线程的数量?#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUMTHREADS 2 //can be anything higher than 1 to cause still reachables
void *thread(void *arg)
{
(void)arg;
pthread_exit(EXIT_SUCCESS);
}
int main(void)
{
int i;
pthread_t threads[NUMTHREADS];
i = -1;
while (++i < NUMTHREADS)
pthread_create(threads + i, NULL, &thread, NULL);
i = -1;
while (++i < NUMTHREADS)
pthread_join(threads[i], NULL);
return (0);
}
在您的thread
函数中,您正在做:
pthread_exit(EXIT_SUCCESS);
替换为:
return (void *) 0;
很好,谢谢。以这种方式退出线程有什么缺点吗?您是否也知道是什么在pthread导致这些仍然可达或为什么这个解决方案的工作?- - - - - -Modin
[linux,至少]pthread_create
的实现不把你给它的线程函数的参数(例如在你的情况下thread
)作为给clone
系统调用的线程启动地址。它将指针指向一个内部/隐藏的"帮助器"。
- 一些线程本地存储的初始化,等等(可能需要调用
malloc
)。 - 调用"real"函数
- TLS清理/析构函数
如果我们调用pthread_exit
,我们就绕过了步骤(3)。
要查看详细信息,我们必须获得glibc
源代码,并在nptl/pthread_create.c
中查找由于不返回而被绕过的10个左右步骤。
就我个人而言,我总是"放松"。我的调用堆栈使用return (void *)
,并且只调用pthread_exit
作为"中止">
编辑:
如果我们看pthread_exit
的源代码,它调用了__do_cancel
[一个内部函数]。就像这样:
pthread_cancel(pthread_self());
给定[修改过的]程序:
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#define NUMTHREADS 8 // can be anything higher than 1 to cause still reachables
void *
thread(void *arg)
{
#if DOEXIT
(void) arg;
pthread_exit(EXIT_SUCCESS);
#else
return (void *) 0;
#endif
}
int
main(void)
{
int i;
pthread_t threads[NUMTHREADS];
i = -1;
while (++i < NUMTHREADS)
pthread_create(threads + i, NULL, &thread, NULL);
i = -1;
while (++i < NUMTHREADS)
pthread_join(threads[i], NULL);
return (0);
}
注意在下面的测试输出中,valgrind
命令为:
valgrind --leak-check=full --show-leak-kinds=all -s ./fix0
下面是用-DDOEXIT=1
编译的输出(pthread_exit
):
==1659955== Memcheck, a memory error detector
==1659955== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1659955== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==1659955== Command: ./fix0
==1659955==
==1659955==
==1659955== HEAP SUMMARY:
==1659955== in use at exit: 1,616 bytes in 4 blocks
==1659955== total heap usage: 13 allocs, 9 frees, 3,848 bytes allocated
==1659955==
==1659955== 21 bytes in 1 blocks are still reachable in loss record 1 of 4
==1659955== at 0x483780B: malloc (vg_replace_malloc.c:309)
==1659955== by 0x401C13D: strdup (strdup.c:42)
==1659955== by 0x4016D0A: _dl_load_cache_lookup (dl-cache.c:306)
==1659955== by 0x4009592: _dl_map_object (dl-load.c:2107)
==1659955== by 0x4013A7D: dl_open_worker (dl-open.c:217)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x401363D: _dl_open (dl-open.c:588)
==1659955== by 0x49F5250: do_dlopen (dl-libc.c:96)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x49F5E02: _dl_catch_error (dl-error-skeleton.c:215)
==1659955== by 0x49F5356: dlerror_run (dl-libc.c:46)
==1659955== by 0x49F53E9: __libc_dlopen_mode (dl-libc.c:195)
==1659955==
==1659955== 21 bytes in 1 blocks are still reachable in loss record 2 of 4
==1659955== at 0x483780B: malloc (vg_replace_malloc.c:309)
==1659955== by 0x400BCEF: _dl_new_object (dl-object.c:163)
==1659955== by 0x400649F: _dl_map_object_from_fd (dl-load.c:1002)
==1659955== by 0x4009319: _dl_map_object (dl-load.c:2241)
==1659955== by 0x4013A7D: dl_open_worker (dl-open.c:217)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x401363D: _dl_open (dl-open.c:588)
==1659955== by 0x49F5250: do_dlopen (dl-libc.c:96)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x49F5E02: _dl_catch_error (dl-error-skeleton.c:215)
==1659955== by 0x49F5356: dlerror_run (dl-libc.c:46)
==1659955== by 0x49F53E9: __libc_dlopen_mode (dl-libc.c:195)
==1659955==
==1659955== 384 bytes in 1 blocks are still reachable in loss record 3 of 4
==1659955== at 0x4839B1A: calloc (vg_replace_malloc.c:762)
==1659955== by 0x401142F: _dl_check_map_versions (dl-version.c:274)
==1659955== by 0x4013B25: dl_open_worker (dl-open.c:266)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x401363D: _dl_open (dl-open.c:588)
==1659955== by 0x49F5250: do_dlopen (dl-libc.c:96)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x49F5E02: _dl_catch_error (dl-error-skeleton.c:215)
==1659955== by 0x49F5356: dlerror_run (dl-libc.c:46)
==1659955== by 0x49F53E9: __libc_dlopen_mode (dl-libc.c:195)
==1659955== by 0x48AE45A: pthread_cancel_init (unwind-forcedunwind.c:53)
==1659955== by 0x48AE673: _Unwind_ForcedUnwind (unwind-forcedunwind.c:127)
==1659955==
==1659955== 1,190 bytes in 1 blocks are still reachable in loss record 4 of 4
==1659955== at 0x4839B1A: calloc (vg_replace_malloc.c:762)
==1659955== by 0x400BA11: _dl_new_object (dl-object.c:73)
==1659955== by 0x400649F: _dl_map_object_from_fd (dl-load.c:1002)
==1659955== by 0x4009319: _dl_map_object (dl-load.c:2241)
==1659955== by 0x4013A7D: dl_open_worker (dl-open.c:217)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x401363D: _dl_open (dl-open.c:588)
==1659955== by 0x49F5250: do_dlopen (dl-libc.c:96)
==1659955== by 0x49F5D66: _dl_catch_exception (dl-error-skeleton.c:196)
==1659955== by 0x49F5E02: _dl_catch_error (dl-error-skeleton.c:215)
==1659955== by 0x49F5356: dlerror_run (dl-libc.c:46)
==1659955== by 0x49F53E9: __libc_dlopen_mode (dl-libc.c:195)
==1659955==
==1659955== LEAK SUMMARY:
==1659955== definitely lost: 0 bytes in 0 blocks
==1659955== indirectly lost: 0 bytes in 0 blocks
==1659955== possibly lost: 0 bytes in 0 blocks
==1659955== still reachable: 1,616 bytes in 4 blocks
==1659955== suppressed: 0 bytes in 0 blocks
==1659955==
==1659955== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
以下是-DDOEXIT=0
(return (void *) 0;
)编译后的输出:
==1660133== Memcheck, a memory error detector
==1660133== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==1660133== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==1660133== Command: ./fix0
==1660133==
==1660133==
==1660133== HEAP SUMMARY:
==1660133== in use at exit: 0 bytes in 0 blocks
==1660133== total heap usage: 8 allocs, 8 frees, 2,176 bytes allocated
==1660133==
==1660133== All heap blocks were freed -- no leaks are possible
==1660133==
==1660133== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)