Valgrind工具組提供了一套調試與分析錯誤的工具包,可以幫助你的程序工做的更加準確,更加快速。這些工具之中最有名的是Memcheck。它可以識別不少C或者C++程序中內存相關的錯誤,這些錯誤會致使程序崩潰或者出現不可預知的行爲。html
接下來會以最短的篇幅告訴你如何使用Memcheck來識別你寫的程序中的內存錯誤。你能夠從用戶手冊中獲取Memcheck的完整文檔以及其餘工具的使用說明。linux
在編譯程序時開啓-g
選項來引入調試信息,這樣Memcheck的錯誤信息中可以準確的顯示問題代碼的序號。若是你可以容忍一些性能損失,請使用-O0
選項來編譯程序.使用-O1
方式來編譯程序錯誤信息可能會不許確,雖然大致而言在使用-O1
方式編譯的程序上使用Memcheck沒有問題,並且相比-O0
方式編譯的程序而言性能大爲提高.不推薦使用-O2
或者更高級別來編譯程序,由於Memcheck偶爾會誤報值未初始化的錯誤.數組
若是你的程序按照如下方式運行:函數
myprog arg1 arg2
工具
請使用下述命令來執行內存檢查:性能
valgrind --leak-check=yes myprog arg1 arg2
指針
Memcheck是默認的工具,開啓--leak-check
選項會啓動內存泄露檢查.調試
你的程序會比正常運行慢不少(大概20到30倍),而且會使用更多的內存.Memcheck會記錄檢測到的內存錯誤和內存泄露信息.code
這是咱們的用於示例的C程序代碼,其文件名爲a.c,這段代碼中有一個內存錯誤和內存泄露問題.orm
#include <stdio.h> void f(){ int * x = malloc(10 * sizeof(int)); x[10] = 0; //problem 1: heap block overrun //problem 2: memory leak -- x not freed } int main(){ f(); return 0; }
下面是使用上述C代碼生成程序的makefile文件.
example:example.o gcc -o example example.o example.o:a.c gcc -c -O0 -g -Wall a.c -o example.o .PHONY:clean clean: -rm -rf *.o example
使用下述命令檢查程序中的內存錯誤:
valgrind --leak-check=yes ./example
大多數的錯誤信息和下面的一致,下面展現了內存越界的錯誤:
==5753== Invalid write of size 4 ==5753== at 0x40053B: f (a.c:5) ==5753== by 0x40054B: main (a.c:9) ==5753== Address 0x51fc068 is 0 bytes after a block of size 40 alloc'd ==5753== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5753== by 0x40052E: f (a.c:4) ==5753== by 0x40054B: main (a.c:9)
注意:
Invalid write
告訴你出現了哪種錯誤.由於內存泄露,程序向本不能訪問的內存進行了寫入操做.--num-callers
選項來擴充堆棧軌跡信息.推薦按照提示的順序來修復錯誤.由於後面的錯誤可能由於前面的錯誤致使.不然你會以爲Memcheck很差用.
內存泄露信息以下所示:
==5753== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1 ==5753== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==5753== by 0x40052E: f (a.c:4) ==5753== by 0x40054B: main (a.c:9)
堆棧追蹤信息告訴你泄露的內存在哪裏分配的.Memcheck不能告訴你爲何內存會泄露.
有幾種不一樣的內存泄露方式,其中最重要的兩種類別是:
若是你不理解錯誤信息,請查詢用戶手冊中關於Memcheck錯誤信息的說明,其中舉例說明了Memcheck產生的全部類型的錯誤信息.
Memcheck並不完美,它偶爾會誤報,有些機制能夠抑制這些誤報.(請參考用戶手冊中的減小出錯章節).然而,他在99%的狀況下都不會出錯,因此你須要謹慎地忽略它報告的錯誤信息.畢竟,你也不會忽略編譯器的報警信息.抑制機制對於你不能修改的庫代碼也有用.默認的抑制會影響庫代碼中的內存錯誤.
Memcheck不可以偵測你程序中的全部內存錯誤.好比,他不能識別越界讀,或者對分配到棧區的數組的越界寫入.可是它可以識別能致使你程序崩潰的大多數錯誤.
嘗試使你的程序更加清晰,這樣Memcheck檢測不出錯誤.當你達到這種狀態,你會更容易發現對程序的哪些修改致使Memcheck報告了新的錯誤.數年的Memcheck使用經驗說明,大型程序也可以使用Memcheck. 好比KDE,Firefox等.
請查詢 Valgrind FAQ Valgrind User Manual.使用--tool選項可使用Valgrind中的其餘工具.