Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++

valgrind

Take the following trivial program:

#include <iostream> 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 <call_gmon_start>   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 <call_gmon_start>:   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 <call_gmon_start+0x12>   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 <deregister_tm_clones>:   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 <deregister_tm_clones+0x17>   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 <deregister_tm_clones+0x15>   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 <register_tm_clones>:   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 <register_tm_clones+0x24>   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 <register_tm_clones+0x22>   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 <deregister_tm_clones>   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 <frame_dummy>:   400860:   48 83 3d 80 05 20 00    cmpq   $0x0,0x200580(%rip)        # 600de8 <__JCR_END__>   400867:   00    400868:   74 1e                   je     400888 <frame_dummy+0x28>   40086a:   b8 00 00 00 00          mov    $0x0,%eax   40086f:   48 85 c0                test   %rax,%rax   400872:   74 14                   je     400888 <frame_dummy+0x28>   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 <register_tm_clones>   400885:   0f 1f 00                nopl   (%rax)   400888:   e9 73 ff ff ff          jmpq   400800 <register_tm_clones>   40088d:   90                      nop   40088e:   90                      nop   40088f:   90                      nop  0000000000400890 <main>:   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 <fstream> or <cmath>.

like image 923
sudo make install Avatar asked May 21 '15 14:05

sudo make install


People also ask

How does valgrind detect memory leaks?

valgrind only checks for memory leaks when your program exits. At that point it traces all memory reachable from the stack and global variables, and anything unreachable is considered to be a leak.

What are the problems with Valgrind?

Valgrind reports two types of issues: memory errors and memory leaks. When a program dynamically allocates memory and forgets to later free it, it creates a leak. A memory leak generally won't cause a program to misbehave, crash, or give wrong answers, and is not an urgent situation.

How do I debug Valgrind?

Start up two terminal windows so that you can interact with Valgrind and GDB simultaneously. In one terminal, run Valgrind with the --vgdb-error=0 option. When running with --vgdb-error= n, Valgrind waits for n errors to occur before pausing and waiting for a connection from GDB.


1 Answers

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.

like image 92
edmz Avatar answered Sep 28 '22 00:09

edmz