[英]c pthread still reachables
I'm using pthread in my program.我在我的程序中使用 pthread。 It runs fine but valgrind detects still reachables.
它运行良好,但 valgrind 检测到仍然可达。 Always the same bytes: 1654, 4 blocks.
总是相同的字节:1654,4 个块。 Always the same functions visible in valgrind.
在 valgrind 中始终可见相同的功能。
Valgrind log: 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)
If I limit the program to 1 thread, I never get any still reachables.如果我将程序限制为 1 个线程,我将永远无法获得任何仍然可以访问的内容。 If I limit it to something low like 2, I sometimes do, sometimes don't.
如果我把它限制在像 2 这样的低值,我有时会,有时不会。 Anything high (48) means I almost always get still reachables.
任何高(48)意味着我几乎总是可以到达。
I managed to reproduce the problem without much code, as follows.我设法在没有太多代码的情况下重现了该问题,如下所示。 What am I doing wrong?
我究竟做错了什么? If I am doing nothing wrong and it's just pthread things, why is it making still reachables?
如果我没有做错任何事情而只是 pthread 的事情,为什么它仍然可以访问? And why is it semi-random depending on amount of threads?
为什么它是半随机的,取决于线程的数量?
#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);
}
In your thread
function, you are doing:在您的
thread
函数中,您正在执行以下操作:
pthread_exit(EXIT_SUCCESS);
Replace with:用。。。来代替:
return (void *) 0;
Perfect, thank you.
完美,谢谢。 Any downsides to exiting threads this way?
以这种方式退出线程有什么缺点吗? Do you also have any idea what in pthread is causing these still reachables or why this solution works?
您是否还知道 pthread 中的什么导致这些仍然可访问或为什么此解决方案有效? – Modin
– 莫丁
The [linux, at least] implementation of pthread_create
does not put the argument you give it for the thread function (eg in your case thread
) as the thread start address given to the clone
syscall. pthread_create
的 [linux,至少] 实现不会将您为线程函数(例如在您的情况下为thread
)提供的参数作为提供给clone
系统调用的线程起始地址。 It gives the pointer to an internal/hidden "helper" start function that does:它提供指向内部/隐藏的“帮助”启动函数的指针,该函数执行以下操作:
malloc
).malloc
)。If we call pthread_exit
, we are bypassing step (3).如果我们调用
pthread_exit
,我们将绕过步骤 (3)。
To see the details, we'd have to get the glibc
source and look in nptl/pthread_create.c
to the 10 or so steps that get bypassed by not returning.要查看详细信息,我们必须获取
glibc
源并在nptl/pthread_create.c
中查看因不返回而被绕过的 10 个左右的步骤。
Personally, I've always "unwound" my call stack to use the return (void *)
and only called pthread_exit
as an "abort"就个人而言,我总是“展开”我的调用堆栈以使用
return (void *)
,并且只将pthread_exit
称为“中止”
Edit:编辑:
If we look at the source for pthread_exit
, it calls __do_cancel
[an internal function].如果我们查看
pthread_exit
的源代码,它会调用__do_cancel
[一个内部函数]。 So, it's like doing:所以,这就像做:
pthread_cancel(pthread_self());
Given the [modified] program:鉴于[修改]程序:
#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);
}
Note in the test outputs below, the valgrind
command is:请注意,在下面的测试输出中,
valgrind
命令是:
valgrind --leak-check=full --show-leak-kinds=all -s ./fix0
Here is the output compiled with -DDOEXIT=1
(that does pthread_exit
):这是使用
-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)
Here is the output when compiled with -DDOEXIT=0
(does return (void *) 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)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.