Valgrind: Memory still reachable with trivial program using <iostream>

匿名 (未验证) 提交于 2019-12-03 01:33:01

问题:

Take the following trivial program:

#include  int main() {   return 0; }

If I run this using valgrind, I'm told that there are 72,704 bytes in 1 blocks that are still reachable. There have been extensive discussions on SO about whether or not to worry about still reachable warnings--I'm not concerned about that. I'd just like to understand how simply including a standard library header could cause a still reachable warning, when none of the objects from that library were allocated in the program itself.

Here is the full valgrind output:

$ valgrind --leak-check=full --track-origins=yes --show-reachable=yes ./ValgrindTest ==27671== Memcheck, a memory error detector ==27671== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==27671== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==27671== Command: ./ValgrindTest ==27671==  ==27671==  ==27671== HEAP SUMMARY: ==27671==     in use at exit: 72,704 bytes in 1 blocks ==27671==   total heap usage: 1 allocs, 0 frees, 72,704 bytes allocated ==27671==  ==27671== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1 ==27671==    at 0x4C2AB9D: malloc (vg_replace_malloc.c:296) ==27671==    by 0x4EC060F: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) ==27671==    by 0x400F305: call_init.part.0 (dl-init.c:85) ==27671==    by 0x400F3DE: call_init (dl-init.c:52) ==27671==    by 0x400F3DE: _dl_init (dl-init.c:134) ==27671==    by 0x40016E9: ??? (in /lib/x86_64-linux-gnu/ld-2.15.so) ==27671==  ==27671== LEAK SUMMARY: ==27671==    definitely lost: 0 bytes in 0 blocks ==27671==    indirectly lost: 0 bytes in 0 blocks ==27671==      possibly lost: 0 bytes in 0 blocks ==27671==    still reachable: 72,704 bytes in 1 blocks ==27671==         suppressed: 0 bytes in 0 blocks ==27671==  ==27671== For counts of detected and suppressed errors, rerun with: -v ==27671== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

And an object dump:

$ objdump -d ValgrindTest   ValgrindTest:     file format elf64-x86-64   Disassembly of section .init:  0000000000400718 <_init>:   400718:   48 83 ec 08             sub    $0x8,%rsp   40071c:   e8 8b 00 00 00          callq  4007ac    400721:   48 83 c4 08             add    $0x8,%rsp   400725:   c3                      retq     Disassembly of section .plt:  0000000000400730 <_ZNSt8ios_base4InitC1Ev@plt-0x10>:   400730:   ff 35 ba 08 20 00       pushq  0x2008ba(%rip)        # 600ff0 <_GLOBAL_OFFSET_TABLE_+0x8>   400736:   ff 25 bc 08 20 00       jmpq   *0x2008bc(%rip)        # 600ff8 <_GLOBAL_OFFSET_TABLE_+0x10>   40073c:   0f 1f 40 00             nopl   0x0(%rax)  0000000000400740 <_ZNSt8ios_base4InitC1Ev@plt>:   400740:   ff 25 ba 08 20 00       jmpq   *0x2008ba(%rip)        # 601000 <_GLOBAL_OFFSET_TABLE_+0x18>   400746:   68 00 00 00 00          pushq  $0x0   40074b:   e9 e0 ff ff ff          jmpq   400730 <_init+0x18>  0000000000400750 <__libc_start_main@plt>:   400750:   ff 25 b2 08 20 00       jmpq   *0x2008b2(%rip)        # 601008 <_GLOBAL_OFFSET_TABLE_+0x20>   400756:   68 01 00 00 00          pushq  $0x1   40075b:   e9 d0 ff ff ff          jmpq   400730 <_init+0x18>  0000000000400760 <__cxa_atexit@plt>:   400760:   ff 25 aa 08 20 00       jmpq   *0x2008aa(%rip)        # 601010 <_GLOBAL_OFFSET_TABLE_+0x28>   400766:   68 02 00 00 00          pushq  $0x2   40076b:   e9 c0 ff ff ff          jmpq   400730 <_init+0x18>  0000000000400770 <_ZNSt8ios_base4InitD1Ev@plt>:   400770:   ff 25 a2 08 20 00       jmpq   *0x2008a2(%rip)        # 601018 <_GLOBAL_OFFSET_TABLE_+0x30>   400776:   68 03 00 00 00          pushq  $0x3   40077b:   e9 b0 ff ff ff          jmpq   400730 <_init+0x18>  Disassembly of section .text:  0000000000400780 <_start>:   400780:   31 ed                   xor    %ebp,%ebp   400782:   49 89 d1                mov    %rdx,%r9   400785:   5e                      pop    %rsi   400786:   48 89 e2                mov    %rsp,%rdx   400789:   48 83 e4 f0             and    $0xfffffffffffffff0,%rsp   40078d:   50                      push   %rax   40078e:   54                      push   %rsp   40078f:   49 c7 c0 80 09 40 00    mov    $0x400980,%r8   400796:   48 c7 c1 f0 08 40 00    mov    $0x4008f0,%rcx   40079d:   48 c7 c7 90 08 40 00    mov    $0x400890,%rdi   4007a4:   e8 a7 ff ff ff          callq  400750 <__libc_start_main@plt>   4007a9:   f4                      hlt       4007aa:   90                      nop   4007ab:   90                      nop  00000000004007ac :   4007ac:   48 83 ec 08             sub    $0x8,%rsp   4007b0:   48 8b 05 29 08 20 00    mov    0x200829(%rip),%rax        # 600fe0 <_DYNAMIC+0x1f0>   4007b7:   48 85 c0                test   %rax,%rax   4007ba:   74 02                   je     4007be    4007bc:   ff d0                   callq  *%rax   4007be:   48 83 c4 08             add    $0x8,%rsp   4007c2:   c3                      retq      4007c3:   90                      nop   4007c4:   90                      nop   4007c5:   90                      nop   4007c6:   90                      nop   4007c7:   90                      nop   4007c8:   90                      nop   4007c9:   90                      nop   4007ca:   90                      nop   4007cb:   90                      nop   4007cc:   90                      nop   4007cd:   90                      nop   4007ce:   90                      nop   4007cf:   90                      nop  00000000004007d0 :   4007d0:   b8 37 10 60 00          mov    $0x601037,%eax   4007d5:   55                      push   %rbp   4007d6:   48 2d 30 10 60 00       sub    $0x601030,%rax   4007dc:   48 83 f8 0e             cmp    $0xe,%rax   4007e0:   48 89 e5                mov    %rsp,%rbp   4007e3:   77 02                   ja     4007e7    4007e5:   5d                      pop    %rbp   4007e6:   c3                      retq      4007e7:   b8 00 00 00 00          mov    $0x0,%eax   4007ec:   48 85 c0                test   %rax,%rax   4007ef:   74 f4                   je     4007e5    4007f1:   5d                      pop    %rbp   4007f2:   bf 30 10 60 00          mov    $0x601030,%edi   4007f7:   ff e0                   jmpq   *%rax   4007f9:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)  0000000000400800 :   400800:   b8 30 10 60 00          mov    $0x601030,%eax   400805:   55                      push   %rbp   400806:   48 2d 30 10 60 00       sub    $0x601030,%rax   40080c:   48 c1 f8 03             sar    $0x3,%rax   400810:   48 89 e5                mov    %rsp,%rbp   400813:   48 89 c2                mov    %rax,%rdx   400816:   48 c1 ea 3f             shr    $0x3f,%rdx   40081a:   48 01 d0                add    %rdx,%rax   40081d:   48 d1 f8                sar    %rax   400820:   75 02                   jne    400824    400822:   5d                      pop    %rbp   400823:   c3                      retq      400824:   ba 00 00 00 00          mov    $0x0,%edx   400829:   48 85 d2                test   %rdx,%rdx   40082c:   74 f4                   je     400822    40082e:   5d                      pop    %rbp   40082f:   48 89 c6                mov    %rax,%rsi   400832:   bf 30 10 60 00          mov    $0x601030,%edi   400837:   ff e2                   jmpq   *%rdx   400839:   0f 1f 80 00 00 00 00    nopl   0x0(%rax)  0000000000400840 <__do_global_dtors_aux>:   400840:   80 3d e9 07 20 00 00    cmpb   $0x0,0x2007e9(%rip)        # 601030 <__bss_start>   400847:   75 11                   jne    40085a <__do_global_dtors_aux+0x1a>   400849:   55                      push   %rbp   40084a:   48 89 e5                mov    %rsp,%rbp   40084d:   e8 7e ff ff ff          callq  4007d0    400852:   5d                      pop    %rbp   400853:   c6 05 d6 07 20 00 01    movb   $0x1,0x2007d6(%rip)        # 601030 <__bss_start>   40085a:   f3 c3                   repz retq    40085c:   0f 1f 40 00             nopl   0x0(%rax)  0000000000400860 :   400860:   48 83 3d 80 05 20 00    cmpq   $0x0,0x200580(%rip)        # 600de8 <__JCR_END__>   400867:   00    400868:   74 1e                   je     400888    40086a:   b8 00 00 00 00          mov    $0x0,%eax   40086f:   48 85 c0                test   %rax,%rax   400872:   74 14                   je     400888    400874:   55                      push   %rbp   400875:   bf e8 0d 60 00          mov    $0x600de8,%edi   40087a:   48 89 e5                mov    %rsp,%rbp   40087d:   ff d0                   callq  *%rax   40087f:   5d                      pop    %rbp   400880:   e9 7b ff ff ff          jmpq   400800    400885:   0f 1f 00                nopl   (%rax)   400888:   e9 73 ff ff ff          jmpq   400800    40088d:   90                      nop   40088e:   90                      nop   40088f:   90                      nop  0000000000400890 +0x28>+0x28>+0x22>+0x24>+0x15>+0x17>+0x12>
: 400890: 55 push %rbp 400891: 48 89 e5 mov %rsp,%rbp 400894: b8 00 00 00 00 mov $0x0,%eax 400899: 5d pop %rbp 40089a: c3 retq 000000000040089b <_Z41__static_initialization_and_destruction_0ii>: 40089b: 55 push %rbp 40089c: 48 89 e5 mov %rsp,%rbp 40089f: 48 83 ec 10 sub $0x10,%rsp 4008a3: 89 7d fc mov %edi,-0x4(%rbp) 4008a6: 89 75 f8 mov %esi,-0x8(%rbp) 4008a9: 83 7d fc 01 cmpl $0x1,-0x4(%rbp) 4008ad: 75 27 jne 4008d6 <_Z41__static_initialization_and_destruction_0ii+0x3b> 4008af: 81 7d f8 ff ff 00 00 cmpl $0xffff,-0x8(%rbp) 4008b6: 75 1e jne 4008d6 <_Z41__static_initialization_and_destruction_0ii+0x3b> 4008b8: bf 34 10 60 00 mov $0x601034,%edi 4008bd: e8 7e fe ff ff callq 400740 <_ZNSt8ios_base4InitC1Ev@plt> 4008c2: ba 28 10 60 00 mov $0x601028,%edx 4008c7: be 34 10 60 00 mov $0x601034,%esi 4008cc: bf 70 07 40 00 mov $0x400770,%edi 4008d1: e8 8a fe ff ff callq 400760 <__cxa_atexit@plt> 4008d6: c9 leaveq 4008d7: c3 retq 00000000004008d8 <_GLOBAL__sub_I_main>: 4008d8: 55 push %rbp 4008d9: 48 89 e5 mov %rsp,%rbp 4008dc: be ff ff 00 00 mov $0xffff,%esi 4008e1: bf 01 00 00 00 mov $0x1,%edi 4008e6: e8 b0 ff ff ff callq 40089b <_Z41__static_initialization_and_destruction_0ii> 4008eb: 5d pop %rbp 4008ec: c3 retq 4008ed: 90 nop 4008ee: 90 nop 4008ef: 90 nop 00000000004008f0 <__libc_csu_init>: 4008f0: 48 89 6c 24 d8 mov %rbp,-0x28(%rsp) 4008f5: 4c 89 64 24 e0 mov %r12,-0x20(%rsp) 4008fa: 48 8d 2d df 04 20 00 lea 0x2004df(%rip),%rbp # 600de0 <__init_array_end> 400901: 4c 8d 25 c8 04 20 00 lea 0x2004c8(%rip),%r12 # 600dd0 <__frame_dummy_init_array_entry> 400908: 4c 89 6c 24 e8 mov %r13,-0x18(%rsp) 40090d: 4c 89 74 24 f0 mov %r14,-0x10(%rsp) 400912: 4c 89 7c 24 f8 mov %r15,-0x8(%rsp) 400917: 48 89 5c 24 d0 mov %rbx,-0x30(%rsp) 40091c: 48 83 ec 38 sub $0x38,%rsp 400920: 4c 29 e5 sub %r12,%rbp 400923: 41 89 fd mov %edi,%r13d 400926: 49 89 f6 mov %rsi,%r14 400929: 48 c1 fd 03 sar $0x3,%rbp 40092d: 49 89 d7 mov %rdx,%r15 400930: e8 e3 fd ff ff callq 400718 <_init> 400935: 48 85 ed test %rbp,%rbp 400938: 74 1c je 400956 <__libc_csu_init+0x66> 40093a: 31 db xor %ebx,%ebx 40093c: 0f 1f 40 00 nopl 0x0(%rax) 400940: 4c 89 fa mov %r15,%rdx 400943: 4c 89 f6 mov %r14,%rsi 400946: 44 89 ef mov %r13d,%edi 400949: 41 ff 14 dc callq *(%r12,%rbx,8) 40094d: 48 83 c3 01 add $0x1,%rbx 400951: 48 39 eb cmp %rbp,%rbx 400954: 75 ea jne 400940 <__libc_csu_init+0x50> 400956: 48 8b 5c 24 08 mov 0x8(%rsp),%rbx 40095b: 48 8b 6c 24 10 mov 0x10(%rsp),%rbp 400960: 4c 8b 64 24 18 mov 0x18(%rsp),%r12 400965: 4c 8b 6c 24 20 mov 0x20(%rsp),%r13 40096a: 4c 8b 74 24 28 mov 0x28(%rsp),%r14 40096f: 4c 8b 7c 24 30 mov 0x30(%rsp),%r15 400974: 48 83 c4 38 add $0x38,%rsp 400978: c3 retq 400979: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000400980 <__libc_csu_fini>: 400980: f3 c3 repz retq 400982: 90 nop 400983: 90 nop Disassembly of section .fini: 0000000000400984 <_fini>: 400984: 48 83 ec 08 sub $0x8,%rsp 400988: 48 83 c4 08 add $0x8,%rsp 40098c: c3 retq

For completeness, I'm using:
Ubuntu: 12.04
Valgrind: 3.10.1 3.7.0
g++: 4.8.1

NB: As a side note, this does not happen when I include other headers such as or .

回答1:

It's Valgrind's fault. First, -fsanitize=leak does not show anything. Second, Valgrind itself states that:

First of all: relax, it's probably not a bug, but a feature. Many implementations of the C++ standard libraries use their own memory pool allocators. Memory for quite a number of destructed objects is not immediately freed and given back to the OS, but kept in the pool(s) for later re-use. The fact that the pools are not freed at the exit of the program cause Valgrind to report this memory as still reachable. The behaviour not to free pools at the exit could be called a bug of the library though.

Using GCC, you can force the STL to use malloc and to free memory as soon as possible by globally disabling memory caching. Beware! Doing so will probably slow down your program, sometimes drastically.

With GCC 2.91, 2.95, 3.0 and 3.1, compile all source using the STL with -D__USE_MALLOC. Beware! This was removed from GCC starting with version 3.3.

With GCC 3.2.2 and later, you should export the environment variable GLIBCPP_FORCE_NEW before running your program.

With GCC 3.4 and later, that variable has changed name to GLIBCXX_FORCE_NEW.

[...]

I guess those alleged memory pools are freed after program's termination, in the so-called start-up code that calls main, among the other settings. Internal functions defined outside user's code should be treated as if they didn't exist, that's why Valgrind can't (and shouldn't) see further frees.



回答2:

Consider the following trivial include file:

#ifndef TRIVIAL_INCLUDE_FILE #define TRIVIAL_INCLUDE_FILE static int *x = new x (0); #endif


回答3:

For gcc 6 and higher, a related bug fix arrived:

With gcc 5, you can also get the same warning without including iostream.

So, if you see a similar warning referring to dl-init.c and you are using gcc 5, consider upgrading to a newer version (gcc >=6), or try to compile with clang.



易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!