Valgrind:使用<iostream>,仍然可以使用普通程序访问内存

采取以下简单的程序:

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

如果我使用valgrind运行这个,我被告知72,704 bytes in 1 blocks中有72,704 bytes in 1 blocks still reachable 。 关于是否担心可以警告的问题,我们已经进行了广泛的讨论 – 我并不担心这一点。 我只是想知道如何简单地包括一个标准的库头可能会导致一个仍然可及的警告,当没有从该库中的对象被分配在程序本身。

这里是完整的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) 

和一个对象转储:

 $ 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 

为了完整性,我正在使用:
Ubuntu:12.04
Valgrind:3.10.1 3.7.0
g ++:4.8.1

注意:作为一个方面说明,当我包含其他头文件如<fstream><cmath>时,不会发生这种情况。

这是Valgrind的错。 首先, -fsanitize=leak不显示任何内容。 其次,Valgrind自己说 :

首先:放松,这可能不是一个错误,而是一个function。 C ++标准库的许多实现都使用它们自己的内存池分配器。 相当多的被破坏的对象的内存不会立即释放并返回到操作系统,而是保存在池中供以后重新使用。 在程序结束时没有释放池的事实导致Valgrind报告这个内存仍然可以访问。 在出口处不释放池的行为可能被称为图书馆的错误。

使用GCC,可以通过全局禁用内存caching来强制STL使用malloc并尽快释放内存。 谨防! 这样做可能会减慢你的程序,有时甚至是很大。

使用GCC 2.91,2.95,3.0和3.1,使用STL和-DUSE_MALLOC编译所有源文件。 谨防! 这是从版本3.3开始从GCC中删除。

使用GCC 3.2.2及更高版本,在运行程序之前,应该导出环境variablesGLIBCPP_FORCE_NEW。

使用GCC 3.4及更高版本时,该variables已更名为GLIBCXX_FORCE_NEW。

[…]

我猜这些所谓的内存池程序终止之后被释放,在所谓的调用main启动代码中,在其他设置中。 在用户代码之外定义的内部函数应该被视为不存在,这就是为什么Valgrind不能(也不应该)看到更多的释放。

考虑以下简单的包含文件:

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