web-dev-qa-db-fra.com

Valgrind: la mémoire est toujours accessible avec un programme trivial utilisant <iostream>

Prenez le programme trivial suivant:

#include <iostream>
int main() {
  return 0;
}

Si je lance ceci en utilisant valgrind, on me dit qu'il y a 72,704 bytes in 1 blocks qui sont still reachable. Il y a eu de longues discussions sur SO) pour savoir s'il faut ou non s'inquiéter des avertissements toujours accessibles - cela ne m'inquiète pas. Je voudrais simplement comprendre comment Y compris un en-tête de bibliothèque standard peut provoquer un avertissement toujours accessible, quand aucun des objets de cette bibliothèque n'est alloué dans le programme lui-même.

Voici la sortie complète de valgrind:

$ 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)

Et un vidage d'objet:

$ 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   

Pour être complet, j'utilise:
Ubuntu: 12.04
Valgrind: 3.10.1 3.7.0
g ++: 4.8.1

NB: En remarque, cela ne se produit pas lorsque j'inclus d'autres en-têtes tels que <fstream> ou <cmath>.

68

C'est la faute de Valgrind. Première, -fsanitize=leak ne montre rien. Deuxièmement, Valgrind elle-même déclare que:

Tout d'abord: détendez-vous, ce n'est probablement pas un bug, mais une fonctionnalité. De nombreuses implémentations des bibliothèques standard C++ utilisent leurs propres allocateurs de pool de mémoire. La mémoire d’un grand nombre d’objets détruits n’est pas immédiatement libérée et restituée au système d’exploitation, mais conservée dans le (s) pool (s) pour une utilisation ultérieure. Le fait que les pools ne soient pas libérés à la sortie du programme force Valgrind à signaler que cette mémoire est toujours accessible. Le comportement consistant à ne pas libérer les pools à la sortie peut cependant être qualifié de bogue de la bibliothèque.

En utilisant GCC, vous pouvez forcer la STL à utiliser malloc et à libérer de la mémoire dès que possible en désactivant globalement la mise en cache de la mémoire. Il faut se méfier! Cela ralentirait probablement votre programme, parfois de manière drastique.

Avec GCC 2.91, 2.95, 3.0 et 3.1, compilez toutes les sources à l'aide du STL avec -D__USE_MALLOC. Il faut se méfier! Cela a été retiré de GCC à partir de la version 3.3.

Avec GCC 3.2.2 et versions ultérieures, vous devez exporter la variable d’environnement GLIBCPP_FORCE_NEW avant d’exécuter votre programme.

Avec GCC 3.4 et versions ultérieures, cette variable a changé de nom et devient GLIBCXX_FORCE_NEW.

[...]

Je suppose que ces supposés pools de mémoire sont libérés après la fin du programme , dans le code de démarrage appelé main, parmi les autres réglages. Les fonctions internes définies en dehors du code de l'utilisateur doivent être traitées comme si elles n'existaient pas. C'est pourquoi Valgrind ne peut pas (et ne devrait pas) voir les nouvelles versions libres.

54
edmz

Considérez le fichier include trivial suivant:

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

Pour gcc 6 et supérieur, un correctif lié est arrivé:

Avec gcc 5, vous pouvez également obtenir le même avertissement sans inclure iostream.

Donc, si vous voyez un avertissement similaire faisant référence à dl-init.c et que vous utilisez gcc 5, envisagez de passer à une version plus récente (gcc> = 6) ou essayez de compiler avec clang.

4
Philipp Claßen