Valgrind工具套件提供了許多調試和分析工具,可幫助您使程序更快,更正確。這些工具中最受歡迎的是Memcheck。它能夠檢測許多與C和C ++程序中常見的內存相關的錯誤,這些錯誤可能致使崩潰和不可預測的行爲。html
標準配置提供了許多有用的工具:node
--tool=none
to run Nulgrind (ie. not --tool=nulgrind
).Valgrind 安裝,去官網下載: http://valgrind.org/downloads/current.html#currentios
我當前下載的版本爲valgrind-3.15.0.tar.bz2git
# tar -jxf valgrind-3.15.0.tar.bz2 ——解壓 # cd /home/ranxf/valgrind-3.15.0 # vim README ——查看文檔來確認安裝過程 0. Clone the code from GIT: git clone git://sourceware.org/git/valgrind.git There are further instructions at http://www.valgrind.org/downloads/repository.html. 1. cd into the source directory. 2. Run ./autogen.sh to setup the environment (you need the standard autoconf tools to do so). 3. Continue with the following instructions... To install from a tar.bz2 distribution: 4. Run ./configure, with some options if you wish. The only interesting one is the usual --prefix=/where/you/want/it/installed. 5. Run "make". 6. Run "make install", possibly as root if the destination permissions require that. 7. See if it works. Try "valgrind ls -l". Either this works, or it bombs out with some complaint. In that case, please let us know (see http://valgrind.org/support/bug_reports.html). # ./configure --prefix=/workdisk/valgrind/ # 配置安裝路徑 # make # 從makefile中讀取指令,而後編譯 # make instal # 從makefile中讀取指令,安裝到指定位置
# vim /etc/profile
export PATH="$PATH:/workdisk/valgrind/bin"(環境變量配置)
cd /workdisk/valgrind/bingithub
# ./valgrind ls -l ==31242== Memcheck, a memory error detector ==31242== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31242== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==31242== Command: ls -l ==31242== 總用量 836 -rwxr-xr-x 1 root root 44737 8月 27 10:41 callgrind_annotate -rwxr-xr-x 1 root root 12673 8月 27 10:41 callgrind_control -rwxr-xr-x 1 root root 33535 8月 27 10:41 cg_annotate -rwxr-xr-x 1 root root 10418 8月 27 10:41 cg_diff -rwxr-xr-x 1 root root 315872 8月 27 10:41 cg_merge -rwxr-xr-x 1 root root 24398 8月 27 10:41 ms_print -rwxr-xr-x 1 root root 76816 8月 27 10:41 valgrind -rwxr-xr-x 1 root root 104136 8月 27 10:41 valgrind-di-server -rwxr-xr-x 1 root root 30176 8月 27 10:41 valgrind-listener -rwxr-xr-x 1 root root 180680 8月 27 10:41 vgdb ==31242== ==31242== HEAP SUMMARY: ==31242== in use at exit: 19,848 bytes in 17 blocks ==31242== total heap usage: 228 allocs, 211 frees, 102,284 bytes allocated ==31242== ==31242== LEAK SUMMARY: ==31242== definitely lost: 0 bytes in 0 blocks ==31242== indirectly lost: 0 bytes in 0 blocks ==31242== possibly lost: 0 bytes in 0 blocks ==31242== still reachable: 19,848 bytes in 17 blocks ==31242== suppressed: 0 bytes in 0 blocks ==31242== Rerun with --leak-check=full to see details of leaked memory ==31242== ==31242== For lists of detected and suppressed errors, rerun with: -s ==31242== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
./valgrind --leak-check=full ls -l ==31322== Memcheck, a memory error detector ==31322== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31322== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==31322== Command: ls -l ==31322== 總用量 836 -rwxr-xr-x 1 root root 44737 8月 27 10:41 callgrind_annotate -rwxr-xr-x 1 root root 12673 8月 27 10:41 callgrind_control -rwxr-xr-x 1 root root 33535 8月 27 10:41 cg_annotate -rwxr-xr-x 1 root root 10418 8月 27 10:41 cg_diff -rwxr-xr-x 1 root root 315872 8月 27 10:41 cg_merge -rwxr-xr-x 1 root root 24398 8月 27 10:41 ms_print -rwxr-xr-x 1 root root 76816 8月 27 10:41 valgrind -rwxr-xr-x 1 root root 104136 8月 27 10:41 valgrind-di-server -rwxr-xr-x 1 root root 30176 8月 27 10:41 valgrind-listener -rwxr-xr-x 1 root root 180680 8月 27 10:41 vgdb ==31322== ==31322== HEAP SUMMARY: ==31322== in use at exit: 19,848 bytes in 17 blocks ==31322== total heap usage: 228 allocs, 211 frees, 102,284 bytes allocated ==31322== ==31322== LEAK SUMMARY: ==31322== definitely lost: 0 bytes in 0 blocks ==31322== indirectly lost: 0 bytes in 0 blocks ==31322== possibly lost: 0 bytes in 0 blocks ==31322== still reachable: 19,848 bytes in 17 blocks ==31322== suppressed: 0 bytes in 0 blocks ==31322== Reachable blocks (those to which a pointer was found) are not shown. ==31322== To see them, rerun with: --leak-check=full --show-leak-kinds=all ==31322== ==31322== For lists of detected and suppressed errors, rerun with: -s ==31322== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
用法: valgrind [options] prog-and-args
[options]: 經常使用選項,適用於全部Valgrind工具vim
最經常使用的命令格式:數組
valgrind --tool=memcheck --leak-check=full ./test緩存
-h –help 顯示幫助信息。(除了如下參數,可用幫助-h查看更多信息) --version 顯示valgrind內核的版本,每一個工具都有各自的版本。 -q –quiet 安靜地運行,只打印錯誤信息。 -v –verbose 更詳細的信息, 增長錯誤數統計。 --trace-children=no|yes 跟蹤子線程? [no] --track-fds=no|yes 跟蹤打開的文件描述?[no] --time-stamp=no|yes 增長時間戳到LOG信息? [no] --log-fd=<number> 輸出LOG到描述符文件 [2=stderr] --log-file=<file> 將輸出的信息寫入到filename.PID的文件裏,PID是運行程序的進行ID --log-file-exactly=<file> 輸出LOG信息到 file --log-file-qualifier=<VAR> 取得環境變量的值來作爲輸出信息的文件名。 [none] --log-socket=ipaddr:port 輸出LOG到socket ,ipaddr:port
LOG信息輸出多線程
仍是在-h中查看socket
--xml=yes 將信息以xml格式輸出,只有memcheck可用 --num-callers=<number> show <number> callers in stack traces [12] --error-limit=no|yes 若是太多錯誤,則中止顯示新錯誤? [yes] --error-exitcode=<number> 若是發現錯誤則返回錯誤代碼 [0=disable] --db-attach=no|yes 當出現錯誤,valgrind會自動啓動調試器gdb。[no] --db-command=<command> 啓動調試器的命令行選項[gdb -nw %f %p]
適用於Memcheck工具的相關選項
--leak-check=no|summary|full 要求對leak給出詳細信息? [summary] --leak-resolution=low|med|high how much bt merging in leak check [low] --show-reachable=no|yes show reachable blocks in leak check? [no]
/workdisk# vim /workdisk/testcode/testValgrind.cc # 在該路徑下生成喊如下內容的testValgrind.cc文件(內存未釋放)
#include <iostream> using namespace std; int main() { int *a = new int(2); //delete a; return 0; }
root@ranxf-TEST:/workdisk/testcode# ls testValgrind.cc root@ranxf-TEST:/workdisk/testcode# g++ -g -o testValgrind testValgrind.cc root@ranxf-TEST:/workdisk/testcode# ls testValgrind testValgrind.cc
-o:指定生成可執行文件的名稱。使用方法爲:g++ -o afile file.cpp file.h ... (可執行文件不可與待編譯或連接文件同名,不然會生成相應可執行文件且覆蓋原編譯或連接文件),若是不使用-o選項,則會生成默承認執行文件a.out。
-c:只編譯不連接,只生成目標文件。
-g:添加gdb調試選項。
輸入命令:orkdisk/testcode# /workdisk/valgrind/bin/valgrind --tool=memcheck --leak-check=full ./testValgrind
若是valgrind添加了環境變量,輸入命令能夠在任何路徑下簡化爲:#valgrind --tool=memcheck --leak-check=full ./testValgrin
root@ranxf-TEST:/workdisk/testcode# /workdisk/valgrind/bin/valgrind --tool=memcheck --leak-check=full ./testValgrind ==12862== Memcheck, a memory error detector # 內存錯誤檢測器 ==12862== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==12862== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==12862== Command: ./testValgrind ==12862== ==12862== ==12862== HEAP SUMMARY: # 堆摘要 ==12862== in use at exit: 72,708 bytes in 2 blocks # 退出時使用:2個數據塊中有72708個字節 ==12862== total heap usage: 2 allocs, 0 frees, 72,708 bytes allocated ==12862== ==12862== 4 bytes in 1 blocks are definitely lost in loss record 1 of 2 # 1個塊中的4個字節在丟失記錄1(共2個)中確定丟失 ==12862== at 0x4C2E4B6: operator new(unsigned long) (vg_replace_malloc.c:344) ==12862== by 0x400717: main (testValgrind.cc:7) ==12862== ==12862== LEAK SUMMARY: 泄漏彙總 ==12862== definitely lost: 4 bytes in 1 blocks 確定泄露:1塊中有4個字節 ==12862== indirectly lost: 0 bytes in 0 blocks 間接泄露:0塊0字節 ==12862== possibly lost: 0 bytes in 0 blocks 可能泄露:0塊0字節 ==12862== still reachable: 72,704 bytes in 1 blocks 仍然能夠訪問:1個塊中有72704個字節 ==12862== suppressed: 0 bytes in 0 blocks 抑制:0塊0字節 ==12862== Reachable blocks (those to which a pointer was found) are not shown. 不顯示可訪問塊(找到指針的塊)。 ==12862== To see them, rerun with: --leak-check=full --show-leak-kinds=all 若要查看它們,請使用如下項從新運行:--leak check=full--show leak kinds=all ==12862== ==12862== For lists of detected and suppressed errors, rerun with: -s 對於檢測到的和抑制的錯誤列表,請使用-s從新運行。 ==12862== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) 錯誤摘要:1個上下文中有1個錯誤(禁止:0到0) root@ranxf-TEST:/workdisk/testcode#
Memcheck將內存泄露分爲兩種,一種是確定的內存泄露(definitely lost),一種可能的內存泄露(possibly lost);
Definitely lost 是指已經不可以訪問這塊內存;
Definitely lost又分爲兩種:直接的(direct)泄露和間接的(indirect)泄露
直接泄露是沒有任何指針指向該內存;
間接泄露是指指向該內存的指針都位於內存泄露處;
Possibly lost 是指仍然存在某個指針可以訪問某塊內存,但該指針指向的已經不是該內存首地址。
#include <iostream> using namespace std; int main() { int a[5]; int i,s=0; a[0]=a[1]=a[3]=a[4]=0; for(i=0;i<5;i++) s=s+a[i]; if(s==33) cout<<"sum is 33"<<endl; else cout<<"sum is not 33"<<endl; return 0; }
數組a中的第二個元素未進行初始化,可是在for循環中依然訪問鏈數組a的第二個元素。這就是使用未初始化的元素問題。在使用g++編譯器對該程序編譯並運行,結果以下:
root@ranxf-TEST:/workdisk/testcode# g++ -g -o TectCode1 valgrindTestCode1.cpp root@ranxf-TEST:/workdisk/testcode# ls TectCode1 testValgrind testValgrind.cc valgrindTestCode1.cpp root@ranxf-TEST:/workdisk/testcode# ./TectCode1 sum is not 33
程序在編譯和運行過程當中並無報出任何錯誤,異常和警告。
但實際上,程序存在一個巨大的隱患,那就是對未初始化的內存進行訪問。咱們使用valgrind對該程序進行檢測,結果以下所示:
root@ranxf-TEST:/workdisk/testcode# valgrind ./TectCode1 或者 valgrind --tool=memcheck --leak-check=full ./TectCode1 # valgrind默認爲內存錯誤檢測器 ==22985== Memcheck, a memory error detector ==22985== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==22985== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==22985== Command: ./TectCode1 ==22985== ==22985== Conditional jump or move depends on uninitialised value(s) ==22985== at 0x400910: main (valgrindTestCode1.cpp:10) (此處要求咱們在進行g++編譯時添加-g參數,否則便給不出具體行數的提示) ==22985== sum is not 33 ==22985== ==22985== HEAP SUMMARY: ==22985== in use at exit: 72,704 bytes in 1 blocks ==22985== total heap usage: 2 allocs, 1 frees, 73,728 bytes allocated ==22985== ==22985== LEAK SUMMARY: ==22985== definitely lost: 0 bytes in 0 blocks ==22985== indirectly lost: 0 bytes in 0 blocks ==22985== possibly lost: 0 bytes in 0 blocks ==22985== still reachable: 72,704 bytes in 1 blocks ==22985== suppressed: 0 bytes in 0 blocks ==22985== Rerun with --leak-check=full to see details of leaked memory
從上圖結果中能夠清晰的看到,提示出1個錯誤,提示信息爲:「Conditional jump or move depends on uninitialised value(s)」,而且提示了錯誤位置在源文件test1.cpp中的第10行(此處要求咱們在進行g++編譯時添加-g參數,否則便給不出具體行數的提示)。
1 #include <stdlib.h> 2 #include <iostream> 3 using namespace std; 4 int main() 5 { 6 int len=4; 7 int *pt=(int *)malloc(len*sizeof(int)); 8 int *p=pt; 9 for(int i=0;i<len;i++) 10 p++; 11 *p=5; 12 cout<<"the value of p is"<<*p<<endl; 13 return 0; 14 }
在程序2中,p指針首先指向了malloc出的4個字節的地址。
以後執行了四次自增運算。也就是p指針自增運算後與初始地址相比偏移了32個字節。
偏移後的地址空間在程序中並無申請。因此,p指針變成鏈野指針。
程序中而且又對p的地址空間進行寫操做。這就形成鏈內存讀寫越界的問題。
————————————————
在使用g++編譯器對該程序編譯並運行,結果以下: root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode2 valgrindTestCode2.cpp root@ranxf-TEST:/workdisk/testcode# ./TestCode2 the value of p is5
/workdisk/testcode# valgrind ./TestCode2 ==26714== Memcheck, a memory error detector ==26714== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==26714== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==26714== Command: ./TestCode2 ==26714== ==26714== Invalid write of size 4 ==26714== at 0x400921: main (valgrindTestCode2.cpp:11) ==26714== Address 0x5ab7c90 is 0 bytes after a block of size 16 alloc'd ==26714== at 0x4C2DE96: malloc (vg_replace_malloc.c:309) ==26714== by 0x4008F6: main (valgrindTestCode2.cpp:7) ==26714== ==26714== Invalid read of size 4 ==26714== at 0x40092B: main (valgrindTestCode2.cpp:12) ==26714== Address 0x5ab7c90 is 0 bytes after a block of size 16 alloc'd ==26714== at 0x4C2DE96: malloc (vg_replace_malloc.c:309) ==26714== by 0x4008F6: main (valgrindTestCode2.cpp:7) ==26714== the value of p is5 ==26714== ==26714== HEAP SUMMARY: ==26714== in use at exit: 72,720 bytes in 2 blocks ==26714== total heap usage: 3 allocs, 1 frees, 73,744 bytes allocated ==26714== ==26714== LEAK SUMMARY: ==26714== definitely lost: 16 bytes in 1 blocks ==26714== indirectly lost: 0 bytes in 0 blocks ==26714== possibly lost: 0 bytes in 0 blocks ==26714== still reachable: 72,704 bytes in 1 blocks ==26714== suppressed: 0 bytes in 0 blocks ==26714== Rerun with --leak-check=full to see details of leaked memory ==26714== ==26714== For lists of detected and suppressed errors, rerun with: -s ==26714== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
從上圖結果中能夠清晰的看到,提示出2個錯誤,提示信息分別爲:「Invalid write of size 4」和「Invalid read of size 4」,而且提示了錯誤位置在源文件test2.cpp中的第11行和第12行。而且檢測提示了:「total heap usage: 3 allocs, 1 frees, 73,744 bytes allocated」。有內存泄漏。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char x[50]; int i; for(i=0;i<50;i++) x[i]=i+1; strncpy(x+20,x,20); strncpy(x+20,x,21); strncpy(x,x+20,20); strncpy(x,x+20,21); x[39]='\0'; strcpy(x,x+20); x[39]=39; x[40]='\0'; strcpy(x,x+20); return 0; } 在代碼3中,strncpy(x+20,x,21),strncpy(x,x+20,21),strcpy(x,x+20)這三條語句,在進行字符串複製過程當中,複製與被複制的字符串空間存在交集。
經過複製操做,會改變初始字符串空間中的值。這就是內存覆蓋的問題。在使用g++編譯器對該程序編譯並運行,結果以下: root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode3 valgrindTestCode3.cpp root@ranxf-TEST:/workdisk/testcode# ./TestCode3 root@ranxf-TEST:/workdisk/testcode#
能夠從上圖中發現,程序在編譯和運行過程當中並無報出任何錯誤,異常和警告。
但實際上存在內存覆蓋的問題,當咱們不注意,再去使用原始字符串時,已經不是原來那個字符串了。
咱們使用valgrind對該程序進行檢測,結果以下所示: root@ranxf-TEST:/workdisk/testcode# valgrind ./TestCode3 ==30101== Memcheck, a memory error detector ==30101== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==30101== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==30101== Command: ./TestCode3 ==30101== ==30101== Source and destination overlap in strncpy(0x1fff0003c9, 0x1fff0003b5, 21) ==30101== at 0x4C31706: __strncpy_sse2_unaligned (vg_replace_strmem.c:555) ==30101== by 0x400648: main (valgrindTestCode3.cpp:11) ==30101== ==30101== Source and destination overlap in strncpy(0x1fff0003b5, 0x1fff0003c9, 21) ==30101== at 0x4C31706: __strncpy_sse2_unaligned (vg_replace_strmem.c:555) ==30101== by 0x400680: main (valgrindTestCode3.cpp:13) ==30101== ==30101== Source and destination overlap in strcpy(0x1fff0003a0, 0x1fff0003b4) ==30101== at 0x4C311C6: strcpy (vg_replace_strmem.c:513) ==30101== by 0x4006BA: main (valgrindTestCode3.cpp:18) ==30101== ==30101== ==30101== HEAP SUMMARY: ==30101== in use at exit: 0 bytes in 0 blocks ==30101== total heap usage: 0 allocs, 0 frees, 0 bytes allocated ==30101== ==30101== All heap blocks were freed -- no leaks are possible ==30101== ==30101== For lists of detected and suppressed errors, rerun with: -s ==30101== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0)
提示三個錯誤,紅色標識部分,並提示源文件中的錯誤行號11行,13行和18行
1 #include <iostream> 2 #include <stdlib.h> 3 int main() 4 { 5 int i; 6 char *p=(char *)malloc(10); 7 char *pt=p; 8 for(i=0;i<10;i++) 9 { 10 p[i]='z'; 11 } 12 delete p; 13 pt[1]='x'; 14 free(pt); 15 return 0; 16 }
在程序4中,使用malloc申請空間,使用delete釋放空間,二者不匹配。使用malloc申請了10個字節的空間,只釋放了一個字節空間。另外,對釋放的空間仍然進行了讀寫操做。這些是典型的內存管理錯誤問題。在使用g++編譯器對該程序編譯並運行,結果以下 root@ranxf-TEST:/workdisk/testcode# g++ -g -o TestCode4 valgrindTestCode4.cpp root@ranxf-TEST:/workdisk/testcode# ./TestCode4 *** Error in `./TestCode4': double free or corruption (fasttop): 0x00000000023dfc20 *** …… 已放棄 (核心已轉儲) 程序在運行中報出內存錯誤,但沒有給出具體信息。咱們使用valgrind對該程序進行檢測,結果以下所示 root@ranxf-TEST:/workdisk/testcode# valgrind ./TestCode4 ==31851== Memcheck, a memory error detector ==31851== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==31851== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info ==31851== Command: ./TestCode4 ==31851== ==31851== Mismatched free() / delete / delete [] ==31851== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:586) ==31851== by 0x4007E2: main (valgrindTestCode4.cpp:12) ==31851== Address 0x5ab7c80 is 0 bytes inside a block of size 10 alloc'd ==31851== at 0x4C2DE96: malloc (vg_replace_malloc.c:309) ==31851== by 0x4007A7: main (valgrindTestCode4.cpp:6) ==31851== ==31851== Invalid write of size 1 ==31851== at 0x4007EB: main (valgrindTestCode4.cpp:13) ==31851== Address 0x5ab7c81 is 1 bytes inside a block of size 10 free'd ==31851== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:586) ==31851== by 0x4007E2: main (valgrindTestCode4.cpp:12) ==31851== Block was alloc'd at ==31851== at 0x4C2DE96: malloc (vg_replace_malloc.c:309) ==31851== by 0x4007A7: main (valgrindTestCode4.cpp:6) ==31851== ==31851== Invalid free() / delete / delete[] / realloc() ==31851== at 0x4C2EF90: free (vg_replace_malloc.c:540) ==31851== by 0x4007F9: main (valgrindTestCode4.cpp:14) ==31851== Address 0x5ab7c80 is 0 bytes inside a block of size 10 free'd ==31851== at 0x4C2F440: operator delete(void*) (vg_replace_malloc.c:586) ==31851== by 0x4007E2: main (valgrindTestCode4.cpp:12) ==31851== Block was alloc'd at ==31851== at 0x4C2DE96: malloc (vg_replace_malloc.c:309) ==31851== by 0x4007A7: main (valgrindTestCode4.cpp:6) ==31851== ==31851== ==31851== HEAP SUMMARY: ==31851== in use at exit: 72,704 bytes in 1 blocks ==31851== total heap usage: 2 allocs, 2 frees, 72,714 bytes allocated ==31851== ==31851== LEAK SUMMARY: ==31851== definitely lost: 0 bytes in 0 blocks ==31851== indirectly lost: 0 bytes in 0 blocks ==31851== possibly lost: 0 bytes in 0 blocks ==31851== still reachable: 72,704 bytes in 1 blocks ==31851== suppressed: 0 bytes in 0 blocks ==31851== Rerun with --leak-check=full to see details of leaked memory ==31851== ==31851== For lists of detected and suppressed errors, rerun with: -s ==31851== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 0 from 0) root@ranxf-TEST:/workdisk/testcode#
從上圖結果中能夠清晰的看到,提示出的3個錯誤。
使用malloc申請空間,使用delete釋放空間,二者不匹配問題:
「Mismatched free() / delete / delete []」;
使用malloc申請鏈10個字節的空間,只釋放鏈一個字節空間:
「 Invalid free() / delete / delete[] / realloc()」;
對釋放空間仍然進行讀寫操做:
「Invalid write of size 1」;
如下代碼中分別存在makefile test.cpp tree.cpp tree.h四個文件中
1 /* makefile文件 2 3 test:test.o tree.o 4 g++ -g -o test test.o tree.o 5 tree.o:tree.cpp tree.h 6 g++ -g -c tree.cpp -o tree.o 7 test.o:test.cpp 8 g++ -g -c test.cpp -o test.o 9 10 /* tree.h文件 12 #ifndef _TREE_ 13 #define _TREE_ 14 typedef struct _node{ 15 struct _node *l; 16 struct _node *r; 17 char v; 18 }node; 19 node *mk(node *l,node *r,char val); 20 void nodefr(node *n); 21 #endif 22 23 / * test.cpp文件 25 #include <iostream> 26 #include "tree.h" 27 int main() 28 { 29 node *tree1,*tree2,*tree3; 30 tree1=mk(mk(mk(0,0,'3'),0,'2'),0,'1'); 31 tree2=mk(0,mk(0,mk(0,0,'6'),'5'),'4'); 32 tree3=mk(mk(tree1,tree2,'8'),0,'7'); 33 return 0; 34 } 35 /* tree.cpp文件 37 38 #include <stdlib.h> 39 #include "tree.h" 40 node *mk(node *l,node *r,char val) 41 { 42 node *f=(node *)malloc(sizeof(*f)); 43 f->l=l; 44 f->r=r; 45 f->v=val; 46 return f; 47 } 48 void nodefr(node *n) 49 { 50 if(n){ 51 nodefr(n->l); 52 nodefr(n->r); 53 free(n); 54 } 55 }
在程序5中,使用malloc申請空間後,沒有使用free函數釋放申請的內存地址形成內存泄漏。在使用g++編譯器對該程序編譯並運行,結果以下:
1 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ls 2 makefile test.cpp tree.cpp tree.h 3 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# make 4 g++ -g -c test.cpp -o test.o 5 g++ -g -c tree.cpp -o tree.o 6 g++ -g -o test test.o tree.o 7 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5#
root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ls
makefile test test.cpp test.o tree.cpp tree.h tree.o
root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# ./test
能夠從上圖中發現,程序在編譯和運行過程當中並無報出任何錯誤,異常和警告。但實際上存在內存泄漏的問題。咱們使用valgrind對該程序進行檢測,結果以下所示:
1 root@ranxf-TEST:/workdisk/testcode/valgrindTestCode5# valgrind ./test 2 ==6852== Memcheck, a memory error detector 3 ==6852== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. 4 ==6852== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info 5 ==6852== Command: ./test 6 ==6852== 7 ==6852== 8 ==6852== HEAP SUMMARY: 9 ==6852== in use at exit: 72,896 bytes in 9 blocks 10 ==6852== total heap usage: 9 allocs, 0 frees, 72,896 bytes allocated 11 ==6852== 12 ==6852== LEAK SUMMARY: 13 ==6852== definitely lost: 24 bytes in 1 blocks # 提示直接內存泄露 14 ==6852== indirectly lost: 168 bytes in 7 blocks # 提示間接內存泄露 15 ==6852== possibly lost: 0 bytes in 0 blocks 16 ==6852== still reachable: 72,704 bytes in 1 blocks 17 ==6852== suppressed: 0 bytes in 0 blocks 18 ==6852== Rerun with --leak-check=full to see details of leaked memory 19 ==6852== 20 ==6852== For lists of detected and suppressed errors, rerun with: -s 21 ==6852== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
由此看到:「total heap usage: 8 allocs, 0 frees, 96 bytes allocated」。
提示間接內存泄漏:「indirectly lost: 84 bytes in 7 blocks」;
提示直接內存泄漏:「definitely lost: 12 bytes in 1 blocks」
間接內存泄漏指:指向該內存的指針都位於內存泄漏處;
直接泄漏時指:沒有任何指針指向該內存。
本篇中的代碼樣例及相關內容都來自於學習徐曉鑫女士編著的《後臺開發核心技術與應用實踐》所得,特此聲明。
程序相關源碼下載地址:https://github.com/XiaoYaoNet/Valgrind_Memset
參考文章:
valgrind 用法詳見:http://blog.csdn.net/sduliulun/article/details/7732906