linux背后隱藏着各種豐富的工具,學會這些工具,讓這些工具更好地服務於我們的項目開發,不僅可以提高工作的效率,而且可以增強個人技術力。
參考:http://blog.chinaunix.net/uid-16135252-id-2752984.html
內存檢測工具有以下的幾種:
mtrace、memwatch、splint、valgrind
對比:
mtrace: 無需安裝,使用時包含頭文件mcheck.h,程序中調用mtrace和muntrace方法即可
memwatch: 在需要檢測的.c文件里面包含memwatch.h文件,編譯的時候加上幾個參數即可
splint:需要下載源碼並安裝程序,通過標志和注釋來獲取想要的錯誤信息
valgrind:提供不同的工具來實現不同功能的檢測,需要編譯源碼
各工具的使用
一、mtrace工具
mtrace是三款工具之中是最簡單易用的,mtrace是一個C函數,在<mcheck.h>里聲明及定義,函數原型為:
其實mtrace是類似malloc_hook的malloc handler,只不過mtrace的handler function已由系統為你寫好,但既然如此,系統又怎么知道你想將malloc/free的記錄寫在哪里呢?為此,調用mtrace()前要先設置MALLOC_TRACE環境變量:
「output_file_name」就是儲存檢測結果的文件的名稱。
但是檢測結果的格式是一般人無法理解的,而只要有安裝mtrace的話,就會有一名為mtrace的Perl script,在shell輸入以下指令:
就會將output_file_name的內容轉化成能被理解的語句,例如「No memory leaks」,「0x12345678 Free 10 was never alloc」諸如此類。
例如以下有一函數:(暫且放下single entry single exit的原則)
return 0;
執行后,再用mtrace 將結果輸出:
Memory not freed: ----------------- Address Size Caller 0x08049a90 0x1 at 0x80483fe
最后一行標明有一個大小為1 byte的內存尚未釋放,應該就是指hello
若我們把該段內存釋放:
free(hello);
結果如下:
mtrace的原理是記錄每一對malloc-free的執行,若每一個malloc都有相應的free,則代表沒有內存泄露,對於任何非malloc/free情況下所發生的內存泄露問題,mtrace並不能找出來。
二、memwatch工具
在三種檢測工具當中,設置最簡單的算是memwatch,和dmalloc一樣,它能檢測未釋放的內存、同一段內存被釋放多次、位址存取錯誤及不當使用未分配之內存區域,溢出和下溢等錯誤。請在http://www.linkdata.se/sourcecode.html下載最新版本的Memwatch。
步驟:
- 確保被測工程中有memwatch.c和memwatch.h文件,
- 源碼中每個.c文件中都include頭文件memwatch.h,
- 編譯代碼,gcc后添加-DMEMWATCH 和 -DMW_STDIO(或者-DMEMWATCH_STDIO),還有memwatch.c文件,例如:
gcc -DMEMWATCH -DMW_STDIO test.c memwatch.c -o test
- 運行生成的可執行文件,程序運行結束后,生成的log文件名為memwatch.log,而且在程序執行期間,所有錯誤提示都會顯示在stdout上
如果未生成上述文件,則會寫入memwatNN.log文件,NN為01~99,如果還未成功,則放棄寫log文件。
注:memwatch會使系統速度減慢
三、splint的使用
1.splint是靜態代碼檢測工具,可以檢查包括:
1)Null Dereferences:針對空指針
2)Undefined Values:未初始化數據
3)Types:轉化類型不一致
4)Memory Management:內存管理檢測,如內存泄露
5)sharing:共享存儲空間安全性檢測
6)Function Interfaces:函數接口檢測(參數傳遞等)
7)Control Flow:函數執行分支檢測
8)Buffer Sizes:緩沖區邊界檢查
9)Completeness:完整性檢查,包括未使用變量、函數等
10)Macros(宏隱患檢測等)
2.源碼包安裝:
#tar zxvf splint-3.1.2.src.tgz
#cd splint-3.1.2
#mkdir /usr/local/splint
#./configure --prefix=/usr/local/splint
#make
#make install
#vi ~/.bashrc (或者 sudo gedit ~/.bashrc) ~目錄是/root
向其中添加以下內容:
export LARCH_PATH=/usr/local/splint/share/splint/lib
export LCLIMPORTDIR=/usr/local/splint/share/splint/import
#source ~/.bashrc
#export PATH=/usr/local/splint/bin/splint:$PATH
到此,splint源碼安裝完成。
3.splint提供了三種方式進行檢查的控制,分別是flags標志、 .splintrc配置文件和格式化注釋。
flags: splint支持幾百個標志用來控制檢查和消息報告,使用時標志前加‘+’或‘-’,‘+’標志開啟這個標志,‘-’表示關閉此標志。下面例子展示了flags標志的用法:
splint -showcol a.c //在檢測a.c時,告警消息中列數不被打印
splint -varuse a.c //在檢測a.c時,告警消息中未使用變量告警不被打印
.splintrc配置文件: .splintrc文件中對一些flags做了默認的設定,命令行中指定的flags會覆蓋.splintrc文件中的標志。
格式化注釋:格式化注釋提供一個類型、變量或函數的額外的信息,可以控制標志設置,增加檢查效果。所有格式化注釋都以/*@開始,@*/結束,比如在函數參數前加/*@null@*/,表示該參數可能是NULL,做檢測時,splint會加強對該參數的值的檢測。
四. valgrind使用:
步驟:
1:tar -xf valgrind-3.9.0.tar.bz2
2:./configure
3:make
4:make install(如果失敗,改用root權限)
5:valgrind ls -l(檢查是否正常工作,如果出錯,按照提示安裝相應文件)
下面的工具是valgrind安裝時的標准配置:
Memcheck:用於檢測內存錯誤。它幫助c和c++的程序更正確。
Cachegrind:用於分析cache和分支預測。它幫助程序執行得更快。
Callgrind:用於函數調用的分析。
Helgrind:用於分析多線程。
DRD:也用於分析多線程。與Helgrind類似,但是用不同的分析技術,所以可以檢測不同的問題。
Massif:用於分析堆。它幫助程序精簡內存的使用。
SGcheck:檢測棧和全局數組溢出的實驗性工具,它和Memcheck互補使用。
--leak-check=yes打開內存泄露檢測細節
--tool=helgrind使用Helgrind工具檢測線程錯誤
假設hello是可執行程序:可能的使用方法如下
valgrind --leak-check=yes ./hello
或者valgrind ./hello
終端上顯示檢測信息。