简体   繁体   English

为什么 valgrind 仅通过多次运行程序就报告不同的结果(没有泄漏可能/仍然可以到达)?

[英]Why does valgrind report different results (no leaks are possible / still reachable) just by running the program multiple times?

While debugging a random segmentation fault, I ran valgrind, running the same program multiple times I get different results.在调试随机分段错误时,我运行了 valgrind,多次运行相同的程序得到不同的结果。 Here is a simplified version of the program (I did not get aa random segmentation fault on this simplified version):这是程序的简化版本(我没有在这个简化版本上遇到随机分段错误):

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

pthread_t* tid;
pthread_t prodId;
int numberThreads = 0;

void *worker(void *arg);
void *producer(void *arg);

int main(int argc, char** argv) {
    numberThreads = atoi((char *) argv[1]);
    tid = (pthread_t*) malloc(sizeof (pthread_t) * numberThreads);
    pthread_create(&prodId, NULL, producer, &prodId);
    pthread_join(prodId, NULL);
    free(tid);
    return (EXIT_SUCCESS);
}

void *producer(void *arg) {
    for (int x = 0; x < numberThreads; x++)
        pthread_create(&(tid[x]), NULL, worker, &(tid[x]));
    for (int x = 0; x < numberThreads; x++)
        pthread_join(tid[x], NULL);
    pthread_exit(NULL);
}

void *worker(void *arg) {
    pthread_exit(NULL);
}

Here is the output of running the program a few times consecutively:下面是连续运行几次程序的output:

$ valgrind --leak-check=full --leak-check=full --show-leak-kinds=all  ./memleek 1
==3044== Memcheck, a memory error detector
==3044== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3044== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3044== Command: ./memleek 1
==3044== 
==3044== 
==3044== HEAP SUMMARY:
==3044==     in use at exit: 0 bytes in 0 blocks
==3044==   total heap usage: 8 allocs, 8 frees, 2,222 bytes allocated
==3044== 
==3044== All heap blocks were freed -- no leaks are possible
==3044== 
==3044== For counts of detected and suppressed errors, rerun with: -v
==3044== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ 
$ 
$ valgrind --leak-check=full --leak-check=full --show-leak-kinds=all  ./memleek 2
==3047== Memcheck, a memory error detector
==3047== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3047== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3047== Command: ./memleek 2
==3047== 
==3047== 
==3047== HEAP SUMMARY:
==3047==     in use at exit: 0 bytes in 0 blocks
==3047==   total heap usage: 9 allocs, 9 frees, 2,502 bytes allocated
==3047== 
==3047== All heap blocks were freed -- no leaks are possible
==3047== 
==3047== For counts of detected and suppressed errors, rerun with: -v
==3047== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
$
$ valgrind --leak-check=full --leak-check=full --show-leak-kinds=all  ./memleek 2
==3051== Memcheck, a memory error detector
==3051== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3051== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3051== Command: ./memleek 2
==3051== 
==3051== 
==3051== HEAP SUMMARY:
==3051==     in use at exit: 0 bytes in 0 blocks
==3051==   total heap usage: 9 allocs, 9 frees, 2,502 bytes allocated
==3051== 
==3051== All heap blocks were freed -- no leaks are possible
==3051== 
==3051== For counts of detected and suppressed errors, rerun with: -v
==3051== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
$
$ valgrind --leak-check=full --leak-check=full --show-leak-kinds=all  ./memleek 2
==3055== Memcheck, a memory error detector
==3055== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==3055== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==3055== Command: ./memleek 2
==3055== 
==3055== 
==3055== HEAP SUMMARY:
==3055==     in use at exit: 1,614 bytes in 4 blocks
==3055==   total heap usage: 9 allocs, 5 frees, 2,502 bytes allocated
==3055== 
==3055== 36 bytes in 1 blocks are still reachable in loss record 1 of 4
==3055==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==3055==    by 0x401AE89: strdup (strdup.c:42)
==3055==    by 0x4016676: _dl_load_cache_lookup (dl-cache.c:311)
==3055==    by 0x4008A87: _dl_map_object (dl-load.c:2336)
==3055==    by 0x4013B13: dl_open_worker (dl-open.c:237)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x4013608: _dl_open (dl-open.c:660)
==3055==    by 0x517431C: do_dlopen (dl-libc.c:87)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x51743AE: dlerror_run (dl-libc.c:46)
==3055==    by 0x5174421: __libc_dlopen_mode (dl-libc.c:163)
==3055==    by 0x4E4966A: pthread_cancel_init (unwind-forcedunwind.c:52)
==3055== 
==3055== 36 bytes in 1 blocks are still reachable in loss record 2 of 4
==3055==    at 0x4C2BBAF: malloc (vg_replace_malloc.c:299)
==3055==    by 0x400B4D3: _dl_new_object (dl-object.c:165)
==3055==    by 0x400587C: _dl_map_object_from_fd (dl-load.c:1000)
==3055==    by 0x400874B: _dl_map_object (dl-load.c:2470)
==3055==    by 0x4013B13: dl_open_worker (dl-open.c:237)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x4013608: _dl_open (dl-open.c:660)
==3055==    by 0x517431C: do_dlopen (dl-libc.c:87)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x51743AE: dlerror_run (dl-libc.c:46)
==3055==    by 0x5174421: __libc_dlopen_mode (dl-libc.c:163)
==3055==    by 0x4E4966A: pthread_cancel_init (unwind-forcedunwind.c:52)
==3055== 
==3055== 360 bytes in 1 blocks are still reachable in loss record 3 of 4
==3055==    at 0x4C2DBC5: calloc (vg_replace_malloc.c:711)
==3055==    by 0x4010FBD: _dl_check_map_versions (dl-version.c:293)
==3055==    by 0x4014076: dl_open_worker (dl-open.c:286)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x4013608: _dl_open (dl-open.c:660)
==3055==    by 0x517431C: do_dlopen (dl-libc.c:87)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x51743AE: dlerror_run (dl-libc.c:46)
==3055==    by 0x5174421: __libc_dlopen_mode (dl-libc.c:163)
==3055==    by 0x4E4966A: pthread_cancel_init (unwind-forcedunwind.c:52)
==3055==    by 0x4E49853: _Unwind_ForcedUnwind (unwind-forcedunwind.c:126)
==3055==    by 0x4E47D7F: __pthread_unwind (unwind.c:121)
==3055== 
==3055== 1,182 bytes in 1 blocks are still reachable in loss record 4 of 4
==3055==    at 0x4C2DBC5: calloc (vg_replace_malloc.c:711)
==3055==    by 0x400B215: _dl_new_object (dl-object.c:75)
==3055==    by 0x400587C: _dl_map_object_from_fd (dl-load.c:1000)
==3055==    by 0x400874B: _dl_map_object (dl-load.c:2470)
==3055==    by 0x4013B13: dl_open_worker (dl-open.c:237)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x4013608: _dl_open (dl-open.c:660)
==3055==    by 0x517431C: do_dlopen (dl-libc.c:87)
==3055==    by 0x400F643: _dl_catch_error (dl-error.c:187)
==3055==    by 0x51743AE: dlerror_run (dl-libc.c:46)
==3055==    by 0x5174421: __libc_dlopen_mode (dl-libc.c:163)
==3055==    by 0x4E4966A: pthread_cancel_init (unwind-forcedunwind.c:52)
==3055== 
==3055== LEAK SUMMARY:
==3055==    definitely lost: 0 bytes in 0 blocks
==3055==    indirectly lost: 0 bytes in 0 blocks
==3055==      possibly lost: 0 bytes in 0 blocks
==3055==    still reachable: 1,614 bytes in 4 blocks
==3055==         suppressed: 0 bytes in 0 blocks
==3055== 
==3055== For counts of detected and suppressed errors, rerun with: -v
==3055== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$ 

I noticed that if I run 4 workers, by passing 4 as the first argument, it constantly says我注意到,如果我运行 4 个工人,通过传递 4 作为第一个参数,它不断说

still reachable: 1,614 bytes in 4 blocks仍然可以访问:4 个块中的 1,614 个字节

Considering that according to this , the "still reachable" category within Valgrind's leak report refers to allocations that fit only the first definition of "memory leak".考虑到根据这一点,Valgrind 的泄漏报告中的“仍然可以访问”类别是指仅符合“内存泄漏”的第一个定义的分配。 These blocks were not freed, but they could have been freed (if the programmer had wanted to) because the program still was keeping track of pointers to those memory blocks.这些块没有被释放,但它们本来可以被释放(如果程序员想要的话),因为程序仍在跟踪指向那些 memory 块的指针。

Well, I want to free these blocks.好吧,我想释放这些块。 Can anyone show me how?谁能告诉我怎么做? Thank you!谢谢!

I tried running your program and I saw the same behavior.我试着运行你的程序,我看到了同样的行为。 I also found that removing one row, the pthread_exit in the workers, removed the valgrind warning about still reachable memory.我还发现删除工人中的 pthread_exit 一行,删除了关于仍然可以到达 memory 的 valgrind 警告。

I started to suspect glibc, and this was confirmed by a similar SO question/answer: glibc oddity with Valgrind我开始怀疑 glibc,这得到了类似的 SO 问题/答案的证实: glibc 怪异与 Valgrind

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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