Valgrind 快速入門

1. 介紹

Valgrind工具組提供了一套調試與分析錯誤的工具包,可以幫助你的程序工做的更加準確,更加快速。這些工具之中最有名的是Memcheck。它可以識別不少C或者C++程序中內存相關的錯誤,這些錯誤會致使程序崩潰或者出現不可預知的行爲。html

接下來會以最短的篇幅告訴你如何使用Memcheck來識別你寫的程序中的內存錯誤。你能夠從用戶手冊中獲取Memcheck的完整文檔以及其餘工具的使用說明。linux

2. 準備你的程序

在編譯程序時開啓-g選項來引入調試信息,這樣Memcheck的錯誤信息中可以準確的顯示問題代碼的序號。若是你可以容忍一些性能損失,請使用-O0選項來編譯程序.使用-O1方式來編譯程序錯誤信息可能會不許確,雖然大致而言在使用-O1方式編譯的程序上使用Memcheck沒有問題,並且相比-O0方式編譯的程序而言性能大爲提高.不推薦使用-O2或者更高級別來編譯程序,由於Memcheck偶爾會誤報值未初始化的錯誤.數組

3.在Memcheck下運行你的程序

若是你的程序按照如下方式運行:函數

myprog arg1 arg2工具

請使用下述命令來執行內存檢查:性能

valgrind --leak-check=yes myprog arg1 arg2指針

Memcheck是默認的工具,開啓--leak-check選項會啓動內存泄露檢查.調試

你的程序會比正常運行慢不少(大概20到30倍),而且會使用更多的內存.Memcheck會記錄檢測到的內存錯誤和內存泄露信息.code

4.解釋Memcheck的輸出信息

這是咱們的用於示例的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)

注意:

  • 每個錯誤有不少信息, 請認真閱讀
  • 5732是進程ID,這通常不重要
  • 第一行Invalid write告訴你出現了哪種錯誤.由於內存泄露,程序向本不能訪問的內存進行了寫入操做.
  • 在第一行以後緊跟的堆棧軌跡信息告訴你問題出現的位置. 堆棧軌跡信息可能會很是大,很是使人迷惑,特別是當你使用C++ STL的時候.推薦按照從下到上的順序進行閱讀.若是堆棧軌跡信息不夠,可使用--num-callers選項來擴充堆棧軌跡信息.
  • 代碼地址(例如:0x40054B) 通常不重要,可是有時在追蹤神祕的bug時會頗有用.
  • 一些錯誤信息有第二個部分描述了涉及到的內存地址.這一段代表了寫入的內存正好在malloc函數分配的內存的後面,對應代碼中的第9行.

推薦按照提示的順序來修復錯誤.由於後面的錯誤可能由於前面的錯誤致使.不然你會以爲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不能告訴你爲何內存會泄露.

有幾種不一樣的內存泄露方式,其中最重要的兩種類別是:

  • "definitely lost": 你的程序泄露了內存,請修復這個錯誤.
  • "probably lost": 你的程序泄露了內存,除非你在"玩弄"指針(例如移動指針到分配的內存塊的中間位置)

若是你不理解錯誤信息,請查詢用戶手冊中關於Memcheck錯誤信息的說明,其中舉例說明了Memcheck產生的全部類型的錯誤信息.

5.警告

Memcheck並不完美,它偶爾會誤報,有些機制能夠抑制這些誤報.(請參考用戶手冊中的減小出錯章節).然而,他在99%的狀況下都不會出錯,因此你須要謹慎地忽略它報告的錯誤信息.畢竟,你也不會忽略編譯器的報警信息.抑制機制對於你不能修改的庫代碼也有用.默認的抑制會影響庫代碼中的內存錯誤.

Memcheck不可以偵測你程序中的全部內存錯誤.好比,他不能識別越界讀,或者對分配到棧區的數組的越界寫入.可是它可以識別能致使你程序崩潰的大多數錯誤.

嘗試使你的程序更加清晰,這樣Memcheck檢測不出錯誤.當你達到這種狀態,你會更容易發現對程序的哪些修改致使Memcheck報告了新的錯誤.數年的Memcheck使用經驗說明,大型程序也可以使用Memcheck. 好比KDE,Firefox等.

6.更多信息

請查詢 Valgrind FAQ Valgrind User Manual.使用--tool選項可使用Valgrind中的其餘工具.

相關文章
相關標籤/搜索