一、 安裝
1. autoconf
# wget http://ftp.gnu.org/gnu/autoconf/autoconf-2.69.tar.gz
# tar -zxvf autoconf-2.69.tar.gz
# cd autoconf-2.69
# ./configure
# make; make install
2. automake
# wget http://ftp.gnu.org/gnu/automake/automake-1.14.tar.gz
# tar -zxvf automake-1.14.tar.gz
# cd automake-1.14
# ./bootstrap.sh
# ./configure
# make; make install
3. valgrind
# wget http://valgrind.org/downloads/valgrind-3.9.0.tar.bz2
# tar -jxvf valgrind-3.9.0.tar.bz2
# cd valgrind-3.9.0
# ./autogen.sh
# ./configure
# make; make install
二、快速使用指南
1. 簡介
Valgrind是一款用于記憶體調試、記憶體洩漏檢測以及性能分析的軟體工具套裝。
它最流行的工具是Memcheck, 它能檢測C/C++中大部分的記憶體相關的錯誤。
2. 準備要檢查的程式
程式編譯時使用 “-g”參數,以添加調試資訊,這樣Memcheck的錯誤消息可以精确到行;
編譯時使用“-O0”也有必要,隻是速度會很慢,“-O1”可能會導緻Memecheck的錯誤消息不正确;
3. 在Memcheck下運作程式:
如果你的程式的運作指令如下:
myprog arg1 arg2
則使用如下指令行:
valgrind --leak-check=yes myprog arg1 arg2
Memcheck是valgrind預設的工具,"--leak-check"選項開啟了詳細記憶體洩漏檢測器;
這時程式會比平時運作得慢很多(如,慢20~30倍),并且會消耗更多的記憶體;
程式運作結束後,或你用“CTRL+C”中止程式後,Memcheck将會列出檢測到的記憶體出錯和洩漏的資訊;
4. Memcheck輸出資訊示例說明
下面是一個很簡單的示例C程式,并帶有一個記憶體錯誤和一個記憶體洩漏;
檔案名為:a.c
1 #include <stdlib.h>
2
3 void f(void)
4 {
5 int* x = malloc(10 * sizeof(int));
6 x[10] = 0; // problem 1: heap block overrun
7 } // problem 2: memory leak -- x not freed
8
9 int main(void)
10 {
11 f();
12 return 0;
13 }
Most error messages look like the following, which describes problem 1, the heap block overrun:
錯誤消息如下,描述了問題1, 記憶體寫越界
==19182== Invalid write of size 4
==19182== at 0x804838F: f (example.c:6)
==19182== by 0x80483AB: main (example.c:11)
==19182== Address 0x1BA45050 is 0 bytes after a block of size 40 alloc’d
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (example.c:5)
==19182== by 0x80483AB: main (example.c:11)
需要注意的資訊有:
. 每個錯誤都會有多行資訊說明,需要仔細閱讀.
. 19182是程序ID, 通常不重要;
. 第一行("Invalid write..."),說明了是哪種類型的錯誤;
在這裡,是程式寫越界了
. 第一行之下的行都是函數調用棧跟蹤,說明了問題的發生的地方;
函數調用棧可以很大,如果還使用了C++ STL時,更容易使人混亂;從底向上讀有助于了解;
如果函數調用棧不夠大,可以使用--num-callers選項來擴大;
. 代碼位址(eg. 0x804838F)通常不用關心,有時隻是在跟蹤怪異的bug時有用;
. 有些錯誤資訊有第二個組成部分,包括記憶體位址的描述等;
在這個例子中,這部分的資訊描述了寫記憶體位于第五行的塊配置設定函數malloc()之後.
按照報告的順序修正錯誤很有必要,因為後面的錯誤可能是前面的錯誤造成的;
如果不這麼做,會導緻Memcheck的使用變得很困難;
記憶體洩漏的資訊通常如下:
==19182== 40 bytes in 1 blocks are definitely lost in loss record 1 of 1
==19182== at 0x1B8FF5CD: malloc (vg_replace_malloc.c:130)
==19182== by 0x8048385: f (a.c:5)
==19182== by 0x80483AB: main (a.c:11)
函數調用棧說明了洩漏的記憶體是在哪配置設定的;
但是,Memcheck并不能說明為什麼記憶體洩漏的(忽略"vg_replace_malloc.c",它隻是一個實作細節);
有多種類型的記憶體洩漏,最重要是如下:
. "definitely lost": 你的程式記憶體洩漏了 -- 需要解決它;
. "probably lost": 你的程式記憶體洩漏了,可能需要解決;
除非你對指針做了一些特殊的處理(如将其指向堆的中部)
Memcheck同樣會報告未初始化值的使用,
對于這種情況,通常的消息是"Conditional jump or move depends on uninitialised value(s)";
追蹤這種錯誤的根源可能很難;
可以嘗試使用 “--track-origins=yes”選項來輸出額外的資訊;
但這會使Memcheck運作得更慢,但有可能追查到未初始化值的根源;