简体   繁体   English

c pthread 仍然可以访问

[英]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:它提供指向内部/隐藏的“帮助”启动函数的指针,该函数执行以下操作:

  1. Some initialization of thread local storage, etc (which may need to call malloc ).线程本地存储的一些初始化等(可能需要调用malloc )。
  2. Invokes the "real" function调用“真实”函数
  3. TLS cleanup/destructors TLS 清理/析构函数

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM