Valgrind: Mémoire toujours accessible avec un programme sortingvial utilisant

Prenez le programme sortingvial suivant:

#include  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 le SO pour savoir s’il fallait ou non s’inquiéter des avertissements encore joignables – cela ne me préoccupe pas. Je voudrais juste comprendre comment l’ inclusion d’ un en-tête de bibliothèque standard peut provoquer un avertissement toujours accessible, quand aucun des objects de cette bibliothèque n’a été 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 object de vidage:

 $ objdump -d ValgrindTest ValgrindTest: file format elf64-x86-64 Disassembly of section .init: 0000000000400718 : 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 : 400730: ff 35 ba 08 20 00 pushq 0x2008ba(%rip) # 600ff0  400736: ff 25 bc 08 20 00 jmpq *0x2008bc(%rip) # 600ff8  40073c: 0f 1f 40 00 nopl 0x0(%rax) 0000000000400740 : 400740: ff 25 ba 08 20 00 jmpq *0x2008ba(%rip) # 601000  400746: 68 00 00 00 00 pushq $0x0 40074b: e9 e0 ff ff ff jmpq 400730  0000000000400750 : 400750: ff 25 b2 08 20 00 jmpq *0x2008b2(%rip) # 601008  400756: 68 01 00 00 00 pushq $0x1 40075b: e9 d0 ff ff ff jmpq 400730  0000000000400760 : 400760: ff 25 aa 08 20 00 jmpq *0x2008aa(%rip) # 601010  400766: 68 02 00 00 00 pushq $0x2 40076b: e9 c0 ff ff ff jmpq 400730  0000000000400770 : 400770: ff 25 a2 08 20 00 jmpq *0x2008a2(%rip) # 601018  400776: 68 03 00 00 00 pushq $0x3 40077b: e9 b0 ff ff ff jmpq 400730  Disassembly of section .text: 0000000000400780 : 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  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  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 : 400840: 80 3d e9 07 20 00 00 cmpb $0x0,0x2007e9(%rip) # 601030  400847: 75 11 jne 40085a  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  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  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 : 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 : 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  4008af: 81 7d f8 ff ff 00 00 cmpl $0xffff,-0x8(%rbp) 4008b6: 75 1e jne 4008d6  4008b8: bf 34 10 60 00 mov $0x601034,%edi 4008bd: e8 7e fe ff ff callq 400740  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  4008d6: c9 leaveq 4008d7: c3 retq 00000000004008d8 : 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  4008eb: 5d pop %rbp 4008ec: c3 retq 4008ed: 90 nop 4008ee: 90 nop 4008ef: 90 nop 00000000004008f0 : 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  400901: 4c 8d 25 c8 04 20 00 lea 0x2004c8(%rip),%r12 # 600dd0  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  400935: 48 85 ed test %rbp,%rbp 400938: 74 1c je 400956  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  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 : 400980: f3 c3 repz retq 400982: 90 nop 400983: 90 nop Disassembly of section .fini: 0000000000400984 : 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: Pour , cela ne se produit pas lorsque autres en-têtes tels que ou .

C’est la faute de Valgrind. Premièrement, -fsanitize=leak ne montre rien. Deuxièmement, Valgrind lui-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 pour un certain nombre d’objects détruits n’est pas immédiatement libérée et redonnée au système d’exploitation, mais conservée dans le ou les pools pour une réutilisation ultérieure. Le fait que les pools ne soient pas libérés à la sortie du programme oblige Valgrind à signaler cette mémoire comme étant toujours accessible. Le comportement à ne pas libérer des pools à la sortie pourrait être appelé un bogue de la bibliothèque si.

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 ralentira probablement votre programme, parfois de manière drastique.

Avec GCC 2.91, 2.95, 3.0 et 3.1, comstackz toutes les sources en utilisant la STL avec -D__USE_MALLOC. Il faut se méfier! Cela a été supprimé 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 pour GLIBCXX_FORCE_NEW.

[…]

Je suppose que ces prétendus pools de mémoire sont libérés après la fin du programme, dans le soi-disant code de démarrage qui appelle main , parmi les autres parameters. 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 plus libre.

Considérons le fichier d’inclusion sortingvial suivant:

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

Pour gcc 6 et versions ultérieures, un correctif relatif au bogue est arrivé:

  • Rapport de bogue: “Avertissement concernant la mémoire” toujours accessible “lors de l’utilisation de libstdc ++ à partir de gcc 5”
  • Discussion sur le suiveur de bogues Arch Linux

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

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