2015-05-21 13 views
55

Weźmy następujący trywialny programu:Valgrind: Pamięć wciąż osiągalny z trywialny programu przy <iostream>

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

Jeśli uruchomię to przy użyciu valgrind, jak mi powiedziano, że istnieją 72,704 bytes in 1 blocks które są still reachable. Odbyliśmy obszerne dyskusje na temat tego, czy martwić się jeszcze dostępnymi ostrzeżeniami - nie przejmuję się tym. Chciałbym po prostu zrozumieć, w jaki sposób prosty standardowy nagłówek biblioteki mógłby spowodować, że nadal dostępny jest komunikat ostrzegawczy, gdy żaden z obiektów z tej biblioteki nie został przydzielony w samym programie.

Oto pełna valgrind wyjściowa:

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

i zrzut obiektu:

$ 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 <[email protected]>: 
    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 <[email protected]>: 
    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 <[email protected]>: 
    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 <[email protected]>: 
    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 <[email protected]>: 
    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 <[email protected]> 
    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 <[email protected]> 
    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 <[email protected]> 
    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 

Dla kompletności, używam:
Ubuntu: 12.04
Valgrind: 3.10.1 3.7.0
g ++: 4.8.1

NB: Na marginesie, tak się nie stanie, gdy dołączę inne nagłówki, takie jak <fstream> lub <cmath>.

+1

ubuntu 14.04, g ++ 4.8.2, valgrind 3.10.0 i bez przecieków! Prawdopodobnie wymaga aktualizacji Valgrind. – doqtor

+0

Jesteś przede mną na wszystkich frontach! Zastanawiam się, która aktualizacja to naprawiła. Niestety nie mogę zaktualizować Ubuntu w tej chwili. –

+0

Powinieneś prawdopodobnie wkleić pełne wyjście valgrind. Upewnij się także, że uruchamiasz z --leak-check = full i --track-origins = yes dla lepszej informacji – mjs

Odpowiedz

42

To wina Valgrind jest. Po pierwsze, -fsanitize=leak nic nie pokazuje. Po drugie, samo Valgrind states:

Po pierwsze: relaks, prawdopodobnie nie jest to błąd, ale funkcja. Wiele implementacji standardowych bibliotek C++ wykorzystuje własne alokatory puli o wartości . Pamięć dla wielu zniszczonych obiektów nie jest natychmiast zwalniana i zwracana do systemu operacyjnego, ale przechowywana w pulach w celu późniejszego ponownego użycia. Fakt, że pule nie zostały zwolnione przy wyjściu z programu, powoduje, że Valgrind raportuje tę pamięć jako nieosiągalną jeszcze . Zachowanie się nie do wolnych pul przy wyjściu można nazwać błędem biblioteki.

Korzystając z GCC, można zmusić STL do używania malloc i zwolnienia pamięci jako wkrótce, gdy to możliwe, przez globalne wyłączenie buforowania pamięci. Strzec się! Czy to , więc prawdopodobnie spowolnienie twojego programu, czasami drastycznie.

Z GCC 2.91, 2.95, 3.0 i 3.1, skompiluj wszystkie źródła używając STL z -D__USE_MALLOC. Strzec się! Zostało to usunięte z GCC zaczynając od wersja 3.3.

Z GCC 3.2.2 i nowszymi wersjami należy wyeksportować zmienną środowiskową GLIBCPP_FORCE_NEW przed uruchomieniem programu.

W GCC 3.4 i nowszych zmienna ta zmieniła nazwę na GLIBCXX_FORCE_NEW.

[...]

Chyba te rzekome pule pamięci są uwolnione po zakończenie programu, w tzw kodu startowego, który wywołuje main, między innymi ustawieniami. Funkcje wewnętrzne zdefiniowane poza kodem użytkownika powinny być traktowane tak, jakby nie istniały, dlatego Valgrind nie może (i nie powinien) widzieć dalszych zwolnień.

5

Rozważmy następujący trywialne zawierać plik:

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

Jak to pomaga? – bcumming

+9

Niestety, pytanie zostało poważnie zmienione z formularza, na który odpowiedziałem. Pierwotne pytanie brzmiało: "Chciałbym tylko zrozumieć, w jaki sposób zwykłe dodanie standardowego nagłówka biblioteki mogłoby spowodować, że nadal dostępne jest ostrzeżenie, gdy żaden z obiektów z tej biblioteki nie został przydzielony w samym programie. *" Przykładowy kod odpowiada pytanie. –

+0

Ach, to ma sens. Niestety udało mi się odtworzyć dokładnie ten sam problem bez dołączania żadnych nagłówków. – bcumming