$ valgrind --tool=memcheck --leak-check=full ./main_c ==31416== Memcheck, a memory error detector ==31416== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31416== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==31416== Command: ./main_c ==31416== ==31416== ==31416== HEAP SUMMARY: ==31416== in use at exit: 4 bytes in 1 blocks ==31416== total heap usage: 1 allocs, 0 frees, 4 bytes allocated ==31416== ==31416== 4 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==31416== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299) ==31416== by 0x400537: main (main.c:5) ==31416== ==31416== LEAK SUMMARY: ==31416== definitely lost: 4 bytes in 1 blocks ==31416== indirectly lost: 0 bytes in 0 blocks ==31416== possibly lost: 0 bytes in 0 blocks ==31416== still reachable: 0 bytes in 0 blocks ==31416== suppressed: 0 bytes in 0 blocks ==31416== ==31416== For counts of detected and suppressed errors, rerun with: -v ==31416== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
$ valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all ./main_cpp ==31438== Memcheck, a memory error detector ==31438== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31438== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==31438== Command: ./main_cpp ==31438== ==31438== ==31438== HEAP SUMMARY: ==31438== in use at exit: 72,704 bytes in 1 blocks ==31438== total heap usage: 2 allocs, 1 frees, 72,736 bytes allocated ==31438== ==31438== 72,704 bytes in 1 blocks are still reachable in loss record 1 of 1 ==31438== at 0x4C2DBF6: malloc (vg_replace_malloc.c:299) ==31438== by 0x4EC3EFF: ??? (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.21) ==31438== by 0x40104E9: call_init.part.0 (dl-init.c:72) ==31438== by 0x40105FA: call_init (dl-init.c:30) ==31438== by 0x40105FA: _dl_init (dl-init.c:120) ==31438== by 0x4000CF9: ??? (in /lib/x86_64-linux-gnu/ld-2.23.so) ==31438== ==31438== LEAK SUMMARY: ==31438== definitely lost: 0 bytes in 0 blocks ==31438== indirectly lost: 0 bytes in 0 blocks ==31438== possibly lost: 0 bytes in 0 blocks ==31438== still reachable: 72,704 bytes in 1 blocks ==31438== suppressed: 0 bytes in 0 blocks ==31438== ==31438== For counts of detected and suppressed errors, rerun with: -v ==31438== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
使用 Valgrind 分析 C++ 程序时,有一些问题需要留意。例如,这个程序并没有发生内存泄漏,但是从HEAP SUMMARY可以看到,程序分配了 2 次内存,但却只释放了 1 次内存,为什么会这样呢?
$ g++ -std=c++11 -g -o main_cpp main.cpp $ valgrind --tool=memcheck --leak-check=full ./main_cpp ==31523== Memcheck, a memory error detector ==31523== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31523== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==31523== Command: ./main_cpp ==31523== ==31523== Invalid read of size 4 ==31523== at 0x400AD7: main (main.cpp:7) ==31523== Address 0x5ab5ca8 is 0 bytes after a block of size 40 alloc'd ==31523== at 0x4C2E216: operatornew(unsignedlong) (vg_replace_malloc.c:334) ==31523== by 0x4010D3: __gnu_cxx::new_allocator<int>::allocate(unsignedlong, voidconst*) (new_allocator.h:104) ==31523== by 0x401040: std::allocator_traits<std::allocator<int> >::allocate(std::allocator<int>&, unsignedlong) (alloc_traits.h:491) ==31523== by 0x400F91: std::_Vector_base<int, std::allocator<int> >::_M_allocate(unsignedlong) (stl_vector.h:170) ==31523== by 0x400E7E: std::_Vector_base<int, std::allocator<int> >::_M_create_storage(unsignedlong) (stl_vector.h:185) ==31523== by 0x400D1E: std::_Vector_base<int, std::allocator<int> >::_Vector_base(unsignedlong, std::allocator<int> const&) (stl_vector.h:136) ==31523== by 0x400C11: std::vector<int, std::allocator<int> >::vector(unsignedlong, intconst&, std::allocator<int> const&) (stl_vector.h:291) ==31523== by 0x400AB9: main (main.cpp:6)
#include<iostream> intmain() { int x; if (x == 0) { std::cout << "X is zero" << std::endl; } return0; }
使用 Valgrind 检测这个程序:
1 2 3 4 5 6 7 8 9
$ g++ -std=c++11 -g -o main_cpp main.cpp $ valgrind --tool=memcheck --leak-check=full ./main_cpp ==31554== Memcheck, a memory error detector ==31554== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31554== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info ==31554== Command: ./main_cpp ==31554== ==31554== Conditional jump or move depends on uninitialised value(s) ==31554== at 0x400852: main (main.cpp:6)
(base) sv@sv-NF5280M5:/home/sv/桌面$ vim main.cpp (base) sv@sv-NF5280M5:/home/sv/桌面$ g++ -g -o main_c main.cpp (base) sv@sv-NF5280M5:/home/sv/桌面$ valgrind --tool=memcheck --leak-check=full ./main_c ==1335995== Memcheck, a memory error detector ==1335995== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==1335995== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==1335995== Command: ./main_c ==1335995== 3[z]2[2[y]pq4[2[jk]e1[f]]]ef ==1335995== Use of uninitialised value of size 8 ==1335995== at 0x49ACC38: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28) ==1335995== by 0x10A87C: main (main.cpp:32) ==1335995== ==1335995== Invalid read of size 8 ==1335995== at 0x49ACC38: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28) ==1335995== by 0x10A87C: main (main.cpp:32) ==1335995== Address 0x1e8 is not stack'd, malloc'd or (recently) free'd ==1335995== ==1335995== ==1335995== Process terminating with default action of signal 11 (SIGSEGV): dumping core ==1335995== Access not within mapped region at address 0x1E8 ==1335995== at 0x49ACC38: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (in /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.28) ==1335995== by 0x10A87C: main (main.cpp:32) ==1335995== If you believe this happened as a result of a stack ==1335995== overflow in your program's main thread (unlikely but ==1335995== possible), you can try to increase the size of the ==1335995== main thread stack using the --main-stacksize= flag. ==1335995== The main thread stack size used in this run was 8388608. ==1335995== ==1335995== HEAP SUMMARY: ==1335995== in use at exit: 1,183 bytes in 5 blocks ==1335995== total heap usage: 7 allocs, 2 frees, 74,911 bytes allocated ==1335995== ==1335995== LEAK SUMMARY: ==1335995== definitely lost: 0 bytes in 0 blocks ==1335995== indirectly lost: 0 bytes in 0 blocks ==1335995== possibly lost: 0 bytes in 0 blocks ==1335995== still reachable: 1,183 bytes in 5 blocks ==1335995== suppressed: 0 bytes in 0 blocks ==1335995== Reachable blocks (those to which a pointer was found) are not shown. ==1335995== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==1335995== ==1335995== Use --track-origins=yes to see where uninitialised values come from ==1335995== For lists of detected and suppressed errors, rerun with: -s ==1335995== ERROR SUMMARY: 2 errors from 2contexts (suppressed: 0 from 0) 段错误