調不盡的內存泄漏,用不完的Valgrindhtml
Valgrind 安裝前端
1. 到www.valgrind.org下載最新版valgrind-3.2.3.tar.bz2算法
2. 解壓安裝包:tar –jxvf valgrind-3.2.3.tar.bz2數組
3. 解壓後生成目錄valgrind-3.2.3網絡
4. cd valgrind-3.2.3多線程
5. 運行./autogen.sh設置環境(須要標準的autoconf工具)(可選)socket
6. ./configure;配置Valgrind,生成MakeFile文件,具體參數信息詳見INSTALL文件。通常只須要設置--prefix=/where/you/want/it/installedide
7. Make;編譯Valgrind函數
8. make install;安裝Valgrind工具
Valgrind包含的工具
Valgrind支持不少工具:memcheck,addrcheck,cachegrind,Massif,helgrind和Callgrind等。在運行Valgrind時,你必須指明想用的工具,若是省略工具名,默認運行memcheck。
一、memcheck
memcheck探測程序中內存管理存在的問題。它檢查全部對內存的讀/寫操做,並截取全部的malloc/new/free/delete調用。所以memcheck工具可以探測到如下問題:
1)使用未初始化的內存
2)讀/寫已經被釋放的內存
3)讀/寫內存越界
4)讀/寫不恰當的內存棧空間
5)內存泄漏
6)使用malloc/new/new[]和free/delete/delete[]不匹配。
7)src和dst的重疊
二、cachegrind
cachegrind是一個cache剖析器。它模擬執行CPU中的L1, D1和L2 cache,所以它能很精確的指出代碼中的cache未命中。若是你須要,它能夠打印出cache未命中的次數,內存引用和發生cache未命中的每一行代碼,每個函數,每個模塊和整個程序的摘要。若是你要求更細緻的信息,它能夠打印出每一行機器碼的未命中次數。在x86和amd64上, cachegrind經過CPUID自動探測機器的cache配置,因此在多數狀況下它再也不須要更多的配置信息了。
三、helgrind
helgrind查找多線程程序中的競爭數據。helgrind查找內存地址,那些被多於一條線程訪問的內存地址,可是沒有使用一致的鎖就會被查出。這表示這些地址在多線程間訪問的時候沒有進行同步,極可能會引發很難查找的時序問題。
它主要用來檢查多線程程序中出現的競爭問題。Helgrind 尋找內存中被多個線程訪問,而又沒有一向加鎖的區域,這些區域每每是線程之間失去同步的地方,並且會致使難以發掘的錯誤。Helgrind實現了名爲」Eraser」 的競爭檢測算法,並作了進一步改進,減小了報告錯誤的次數。
四、Callgrind
Callgrind收集程序運行時的一些數據,函數調用關係等信息,還能夠有選擇地進行cache 模擬。在運行結束時,它會把分析數據寫入一個文件。callgrind_annotate能夠把這個文件的內容轉化成可讀的形式。
通常用法:
$valgrind --tool=callgrind ./sec_infod
會在當前目錄下生成callgrind.out.[pid], 若是咱們想結束程序, 能夠
$killall callgrind
而後咱們能夠用
$callgrind_annotate --auto=yes callgrind.out.[pid] > log
$vi log
五、Massif
堆棧分析器,它能測量程序在堆棧中使用了多少內存,告訴咱們堆塊,堆管理塊和棧的大小。Massif能幫助咱們減小內存的使用,在帶有虛擬內存的現代系統中,它還可以加速咱們程序的運行,減小程序停留在交換區中的概率。
六、lackey
lackey是一個示例程序,以其爲模版能夠建立你本身的工具。在程序結束後,它打印出一些基本的關於程序執行統計數據。
Valgrind的參數
用法: valgrind [options] prog-and-args [options]: 經常使用選項,適用於全部Valgrind工具
--tool=<name>
最經常使用的選項。運行 valgrind中名爲toolname的工具。默認memcheck。
-h --help
顯示全部選項的幫助,包括內核和選定的工具二者。
--version
顯示valgrind內核的版本,每一個工具都有各自的版本。
-q --quiet
安靜地運行,只打印錯誤信息。
--verbose
更詳細的信息。
--trace-children=<yes|no>
跟蹤子線程? [default: no]
--track-fds=<yes|no>
跟蹤打開的文件描述?[default: no]
--time-stamp=<yes|no>
增長時間戳到LOG信息? [default: no]
--log-fd=<number>
輸出LOG到描述符文件 [2=stderr]
--log-file=<file>
將輸出的信息寫入到filename.PID的文件裏,PID是運行程序的進行ID
--log-file-exactly=<file>
輸出LOG信息到 file
LOG信息輸出
--xml=yes
將信息以xml格式輸出,只有memcheck可用
--num-callers=<number>
show <number> callers in stack traces [12]
--error-exitcode=<number>
若是發現錯誤則返回錯誤代碼 [0=disable]
--db-attach=<yes|no>
當出現錯誤,valgrind會自動啓動調試器gdb。[default: no]
--db-command=<command>
啓動調試器的命令行選項[gdb -nw %f %p]
適用於Memcheck工具的相關選項:
--leak-check=<no|summary|full>
要求對leak給出詳細信息? Leak是指,存在一塊沒有被引用的內存空間,或沒有被釋放的內存空間,如summary,只反饋一些總結信息,告訴你有多少個malloc,多少個free 等;若是是full將輸出全部的leaks,也就是定位到某一個malloc/free。 [default: summary]
--show-reachable=<yes|no>
若是爲no,只輸出沒有引用的內存leaks,或指向malloc返回的內存塊中部某處的leaks [default: no]
更詳細的參數指令見附錄A。
Valgrind的使用
首先,在編譯程序的時候打開調試模式(gcc編譯器的-g選項)。若是沒有調試信息,即便最好的valgrind工具也將中可以猜想特定的代碼是屬於哪個函數。打開調試選項進行編譯後再用valgrind檢查,valgrind將會給你的個詳細的報告,好比哪一行代碼出現了內存泄漏。
當檢查的是C++程序的時候,還應該考慮另外一個選項 -fno-inline。它使得函數調用鏈很清晰,這樣能夠減小你在瀏覽大型C++程序時的混亂。好比在使用這個選項的時候,用memcheck檢查openoffice就很容易。固然,你可能不會作這項工做,可是使用這一選項使得valgrind生成更精確的錯誤報告和減小混亂。
一些編譯優化選項(好比-O2或者更高的優化選項),可能會使得memcheck提交錯誤的未初始化報告,所以,爲了使得valgrind的報告更精確,在編譯的時候最好不要使用優化選項。
若是程序是經過腳本啓動的,能夠修改腳本里啓動程序的代碼,或者使用--trace-children=yes選項來運行腳本。
下面是用memcheck檢查sample.c的例子
這裏用到的示例程序文件名爲:sample.c(以下所示),選用的編譯器爲gcc。
生成可執行程序
gcc –g sample.c –o sample
圖1
運行Valgrind
valgrind --tool=memcheck ./sample
如下是運行上述命令後的輸出
圖2
左邊顯示相似行號的數字(10297)表示的是 Process ID。
最上面的紅色方框表示的是 valgrind 的版本信息。
中間的紅色方框表示 valgrind 經過運行被測試程序,發現的內存問題。經過閱讀這些信息,能夠發現:
l 這是一個對內存的非法寫操做,非法寫操做的內存是4 bytes。
l 發生錯誤時的函數堆棧,以及具體的源代碼行號。
l 非法寫操做的具體地址空間。
最下面的紅色方框是對發現的內存問題和內存泄漏問題的總結。內存泄漏的大小(40 bytes)也可以被檢測出來。
Valgrind的示例
例1.使用未初始化的內存
代碼以下
#include <stdio.h>
int main()
{
int x;
if(x == 0)
{
printf("X is zero");
}
return 0;
}
Valgrind提示以下
==14222== Conditional jump or move depends on uninitialised value(s)
==14222== at 0x400484: main (sample2.c:6)
X is zero==14222==
==14222== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==14222== malloc/free: in use at exit: 0 bytes in 0 blocks.
==14222== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==14222== For counts of detected errors, rerun with: -v
==14222== All heap blocks were freed -- no leaks are possible.
例2.內存讀寫越界
代碼以下
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[])
{
int len=5;
int i;
int *pt=(int*)malloc(len*sizeof(int));
int *p=pt;
for(i=0;i<len;i++)
{p++;}
*p=5;
printf(「%d」,*p);
return;
}
Valgrind提示以下
==23045== Invalid write of size 4
==23045== at 0x40050A: main (sample2.c:11)
==23045== Address 0x4C2E044 is 0 bytes after a block of size 20 alloc'd
==23045== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==23045== by 0x4004DF: main (sample2.c:7)
==23045==
==23045== Invalid read of size 4
==23045== at 0x400514: main (sample2.c:12)
==23045== Address 0x4C2E044 is 0 bytes after a block of size 20 alloc'd
==23045== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==23045== by 0x4004DF: main (sample2.c:7)
5==23045==
==23045== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 5 from 1)
==23045== malloc/free: in use at exit: 20 bytes in 1 blocks.
==23045== malloc/free: 1 allocs, 0 frees, 20 bytes allocated.
==23045== For counts of detected errors, rerun with: -v
==23045== searching for pointers to 1 not-freed blocks.
==23045== checked 66,584 bytes.
==23045==
==23045== LEAK SUMMARY:
==23045== definitely lost: 20 bytes in 1 blocks.
==23045== possibly lost: 0 bytes in 0 blocks.
==23045== still reachable: 0 bytes in 0 blocks.
==23045== suppressed: 0 bytes in 0 blocks.
==23045== Use --leak-check=full to see details of leaked memory.
例3.src和dst內存覆蓋
代碼以下
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(int argc,char *argv[])
{ char x[50];
int i;
for(i=0;i<50;i++)
{x[i]=i;}
strncpy(x+20,x,20); //Good
strncpy(x+20,x,21); //Overlap
x[39]=’\0’;
strcpy(x,x+20); //Good
x[39]=40;
x[40]=’\0’;
strcpy(x,x+20); //Overlap
return 0;
}
Valgrind提示以下
==24139== Source and destination overlap in strncpy(0x7FEFFFC09, 0x7FEFFFBF5, 21)
==24139== at 0x4A0724F: strncpy (mc_replace_strmem.c:116)
==24139== by 0x400527: main (sample3.c:10)
==24139==
==24139== Source and destination overlap in strcpy(0x7FEFFFBE0, 0x7FEFFFBF4)
==24139== at 0x4A06E47: strcpy (mc_replace_strmem.c:106)
==24139== by 0x400555: main (sample3.c:15)
==24139==
==24139== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 5 from 1)
==24139== malloc/free: in use at exit: 0 bytes in 0 blocks.
==24139== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.
==24139== For counts of detected errors, rerun with: -v
==24139== All heap blocks were freed -- no leaks are possible.
例4.動態內存管理錯誤
常見的內存分配方式分三種:靜態存儲,棧上分配,堆上分配。全局變量屬於靜態存儲,它們是在編譯時就被分配了存儲空間,函數內的局部變量屬於棧上分配,而最靈活的內存使用方式當屬堆上分配,也叫作內存動態分配了。經常使用的內存動態分配函數包括:malloc, alloc, realloc, new等,動態釋放函數包括free, delete。
一旦成功申請了動態內存,咱們就須要本身對其進行內存管理,而這又是最容易犯錯誤的。常見的內存動態管理錯誤包括:
l 申請和釋放不一致
因爲 C++ 兼容 C,而 C 與 C++ 的內存申請和釋放函數是不一樣的,所以在 C++ 程序中,就有兩套動態內存管理函數。一條不變的規則就是採用 C 方式申請的內存就用 C 方式釋放;用 C++ 方式申請的內存,用 C++ 方式釋放。也就是用 malloc/alloc/realloc 方式申請的內存,用 free 釋放;用 new 方式申請的內存用 delete 釋放。在上述程序中,用 malloc 方式申請了內存卻用 delete 來釋放,雖然這在不少狀況下不會有問題,但這絕對是潛在的問題。
l 申請和釋放不匹配
申請了多少內存,在使用完成後就要釋放多少。若是沒有釋放,或者少釋放了就是內存泄露;多釋放了也會產生問題。上述程序中,指針p和pt指向的是同一塊內存,卻被前後釋放兩次。
l 釋放後仍然讀寫
本質上說,系統會在堆上維護一個動態內存鏈表,若是被釋放,就意味着該塊內存能夠繼續被分配給其餘部分,若是內存被釋放後再訪問,就可能覆蓋其餘部分的信息,這是一種嚴重的錯誤,上述程序第16行中就在釋放後仍然寫這塊內存。
下面的一段程序,就包括了內存動態管理中常見的錯誤。
#include <stdlib.h>
#include <stdio.h>
int main(int argc,char *argv[])
{ char *p=(char*)malloc(10);
char *pt=p;
int i;
for(i=0;i<10;i++)
{p[i]=’z’;}
delete p;
p[1]=’a’;
free(pt);
return 0;
}
Valgrind提示以下
==25811== Mismatched free() / delete / delete []
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811== Address 0x4C2F030 is 0 bytes inside a block of size 10 alloc'd
==25811== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==25811== by 0x400620: main (sample4.c:4)
==25811==
==25811== Invalid write of size 1
==25811== at 0x40065D: main (sample4.c:10)
==25811== Address 0x4C2F031 is 1 bytes inside a block of size 10 free'd
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811==
==25811== Invalid free() / delete / delete[]
==25811== at 0x4A0541E: free (vg_replace_malloc.c:233)
==25811== by 0x400668: main (sample4.c:11)
==25811== Address 0x4C2F030 is 0 bytes inside a block of size 10 free'd
==25811== at 0x4A05130: operator delete(void*) (vg_replace_malloc.c:244)
==25811== by 0x400654: main (sample4.c:9)
==25811==
==25811== ERROR SUMMARY: 3 errors from 3 contexts (suppressed: 5 from 1)
==25811== malloc/free: in use at exit: 0 bytes in 0 blocks.
==25811== malloc/free: 1 allocs, 2 frees, 10 bytes allocated.
==25811== For counts of detected errors, rerun with: -v
==25811== All heap blocks were freed -- no leaks are possible.
例5.內存泄漏
代碼以下
#include <stdlib.h>
int main()
{
char *x = (char*)malloc(20);
char *y = (char*)malloc(20);
x=y;
free(x);
free(y);
return 0;
}
Valgrind提示以下
==19013== Invalid free() / delete / delete[]
==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)
==19013== by 0x4004F5: main (sample5.c:8)
==19013== Address 0x4C2E078 is 0 bytes inside a block of size 20 free'd
==19013== at 0x4A0541E: free (vg_replace_malloc.c:233)
==19013== by 0x4004EC: main (sample5.c:7)
==19013==
==19013== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==19013== malloc/free: in use at exit: 20 bytes in 1 blocks.
==19013== malloc/free: 2 allocs, 2 frees, 40 bytes allocated.
==19013== For counts of detected errors, rerun with: -v
==19013== searching for pointers to 1 not-freed blocks.
==19013== checked 66,584 bytes.
==19013==
==19013== LEAK SUMMARY:
==19013== definitely lost: 20 bytes in 1 blocks.
==19013== possibly lost: 0 bytes in 0 blocks.
==19013== still reachable: 0 bytes in 0 blocks.
==19013== suppressed: 0 bytes in 0 blocks.
==19013== Use --leak-check=full to see details of leaked memory.
例6.非法寫/讀
代碼以下
int main()
{
int i, *x;
x = (int *)malloc(10*sizeof(int));
for (i=0; i<11; i++)
x[i] = i;
free(x);
}
Valgrind提示以下
==21483== Invalid write of size 4
==21483== at 0x4004EA: main (sample6.c:6)
==21483== Address 0x4C2E058 is 0 bytes after a block of size 40 alloc'd
==21483== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==21483== by 0x4004C9: main (sample6.c:4)
==21483==
==21483== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==21483== malloc/free: in use at exit: 0 bytes in 0 blocks.
==21483== malloc/free: 1 allocs, 1 frees, 40 bytes allocated.
==21483== For counts of detected errors, rerun with: -v
==21483== All heap blocks were freed -- no leaks are possible.
例7.無效指針
代碼以下
#include <stdlib.h>
int main()
{
char *x = malloc(10);
x[10] = 'a';
free(x);
return 0;
}
Valgrind提示以下
==15262== Invalid write of size 1
==15262== at 0x4004D6: main (sample7.c:5)
==15262== Address 0x4C2E03A is 0 bytes after a block of size 10 alloc'd
==15262== at 0x4A05809: malloc (vg_replace_malloc.c:149)
==15262== by 0x4004C9: main (sample7.c:4)
==15262==
==15262== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==15262== malloc/free: in use at exit: 0 bytes in 0 blocks.
==15262== malloc/free: 1 allocs, 1 frees, 10 bytes allocated.
==15262== For counts of detected errors, rerun with: -v
==15262== All heap blocks were freed -- no leaks are possible.
例8.重複釋放
代碼以下
#include <stdlib.h>
int main()
{
char *x = malloc(10);
free(x);
free(x);
return 0;
}
Valgrind提示以下
==15005== Invalid free() / delete / delete[]
==15005== at 0x4A0541E: free (vg_replace_malloc.c:233)
==15005== by 0x4004DF: main (sample8.c:6)
==15005== Address 0x4C2E030 is 0 bytes inside a block of size 10 free'd
==15005== at 0x4A0541E: free (vg_replace_malloc.c:233)
==15005== by 0x4004D6: main (sample8.c:5)
==15005==
==15005== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 5 from 1)
==15005== malloc/free: in use at exit: 0 bytes in 0 blocks.
==15005== malloc/free: 1 allocs, 2 frees, 10 bytes allocated.
==15005== For counts of detected errors, rerun with: -v
==15005== All heap blocks were freed -- no leaks are possible.
Valgrind的侷限
l Valgrind不對靜態數組(分配在棧上)進行邊界檢查。若是在程序中聲明瞭一個數組:
int main()
{
char x[10];
x[11] = 'a';
}
Valgrind則不會警告你,你能夠把數組改成動態在堆上分配的數組,這樣就可能進行邊界檢查了。這個方法好像有點得不償失的感受。
l Valgrind佔用了更多的內存--可達兩倍於你程序的正常使用量。若是你用Valgrind來檢測使用大量內存的程序就會遇到問題,它可能會用很長的時間來運行測試。大多數狀況下,這都不是問題,即便速度慢也僅是檢測時速度慢,若是你用Valgrind來檢測一個正常運行時速度就很慢的程序,這下問題就大了。 Valgrind不可能檢測出你在程序中犯下的全部錯誤--若是你不檢查緩衝區溢出,Valgrind也不會告訴你代碼寫了它不該該寫的內存。
附錄A:參數指令
基本選項:
這些選項對全部工具都有效。
-h --help
顯示全部選項的幫助,包括內核和選定的工具二者。
--help-debug
和--help相同,而且還能顯示一般只有Valgrind的開發人員使用的調試選項。
--version
顯示Valgrind內核的版本號。工具能夠有他們自已的版本號。這是一種保證工具只在它們能夠運行的內核上工做的一種設置。這樣能夠減小在工具和內核之間版本兼容性致使奇怪問題的機率。
-q --quiet
安靜的運行,只打印錯誤信息。在進行迴歸測試或者有其它的自動化測試機制時會很是有用。
-v --verbose
顯示詳細信息。在各個方面顯示你的程序的額外信息,例如:共享對象加載,使用的重置,執行引擎和工具的進程,異常行爲的警告信息。重複這個標記能夠增長詳細的級別。
-d
調試Valgrind自身發出的信息。一般只有Valgrind開發人員對此感興趣。重複這個標記能夠產生更詳細的輸出。若是你但願發送一個bug報告,經過-v -v -d -d生成的輸出會使你的報告更加有效。
--tool=<toolname> [default: memcheck]
運行toolname指定的Valgrind,例如,Memcheck, Addrcheck, Cachegrind,等等。
--trace-children=<yes|no> [default: no]
當這個選項打開時,Valgrind會跟蹤到子進程中。這常常會致使困惑,並且一般不是你所指望的,因此默認這個選項是關閉的。
--track-fds=<yes|no> [default: no]
當這個選項打開時,Valgrind會在退出時打印一個打開文件描述符的列表。每一個文件描述符都會打印出一個文件是在哪裏打開的棧回溯,和任何與此文件描述符相關的詳細信息好比文件名或socket信息。
--time-stamp=<yes|no> [default: no]
當這個選項打開時,每條信息以前都有一個從程序開始消逝的時間,用天,小時,分鐘,秒和毫秒錶示。
--log-fd=<number> [default: 2, stderr]
指定Valgrind把它全部的消息都輸出到一個指定的文件描述符中去。默認值2, 是標準錯誤輸出(stderr)。注意這可能會干擾到客戶端自身對stderr的使用, Valgrind的輸出與客戶程序的輸出將穿插在一塊兒輸出到stderr。
--log-file=<filename>
指定Valgrind把它全部的信息輸出到指定的文件中。實際上,被建立文件的文件名是由filename、'.'和進程號鏈接起來的(即<filename>.<pid>),從而每一個進程建立不一樣的文件。
--log-file-exactly=<filename>
相似於--log-file,可是後綴".pid"不會被添加。若是設置了這個選項,使用Valgrind跟蹤多個進程,可能會獲得一個亂七八糟的文件。
--log-file-qualifier=<VAR>
當和--log-file一塊兒使用時,日誌文件名將經過環境變量$VAR來篩選。這對於MPI程序是有益的。更多的細節,查看手冊2.3節 "註解"。
--log-socket=<ip-address:port-number>
指定Valgrind輸出全部的消息到指定的IP,指定的端口。當使用1500端口時,端口有可能被忽略。若是不能創建一個到指定端口的鏈接,Valgrind將輸出寫到標準錯誤(stderr)。這個選項常常和一個Valgrind監聽程序一塊兒使用。更多的細節,查看手冊2.3節 "註解"。
錯誤相關選項:
這些選項適用於全部產生錯誤的工具,好比Memcheck, 可是Cachegrind不行。
--xml=<yes|no> [default: no]
當這個選項打開時,輸出將是XML格式。這是爲了使用Valgrind的輸出作爲輸入的工具,例如GUI前端更加容易些。目前這個選項只在Memcheck時生效。
--xml-user-comment=<string>
在XML開頭 附加用戶註釋,僅在指定了--xml=yes時生效,不然忽略。
--demangle=<yes|no> [default: yes]
打開/關閉C++的名字自動解碼。默認打開。當打開時,Valgrind將嘗試着把編碼過的C++名字自動轉回初始狀態。這個解碼器能夠處理g++版本爲2.X,3.X或4.X生成的符號。一個關於名字編碼解碼重要的事實是,禁止文件中的解碼函數名仍然使用他們未解碼的形式。Valgrind在搜尋可用的禁止條目時不對函數名解碼,由於這將使禁止文件內容依賴於Valgrind的名字解碼機制狀態,會使速度變慢,且無心義。
--num-callers=<number> [default: 12]
默認狀況下,Valgrind顯示12層函數調用的函數名有助於肯定程序的位置。能夠經過這個選項來改變這個數字。這樣有助在嵌套調用的層次很深時肯定程序的位置。注意錯誤信息一般只回溯到最頂上的4個函數。(當前函數,和它的3個調用者的位置)。因此這並不影響報告的錯誤總數。這個值的最大值是50。注意高的設置會使Valgrind運行得慢,而且使用更多的內存,可是在嵌套調用層次比較高的程序中很是實用。
--error-limit=<yes|no> [default: yes]
當這個選項打開時,在總量達到10,000,000,或者1,000個不一樣的錯誤,Valgrind中止報告錯誤。這是爲了不錯誤跟蹤機制在錯誤不少的程序下變成一個巨大的性能負擔。
--error-exitcode=<number> [default: 0]
指定若是Valgrind在運行過程當中報告任何錯誤時的退出返回值,有兩種狀況;當設置爲默認值(零)時,Valgrind返回的值將是它模擬運行的程序的返回值。當設置爲非零值時,若是Valgrind發現任何錯誤時則返回這個值。在Valgrind作爲一個測試工具套件的部分使用時這將很是有用,由於使測試工具套件只檢查Valgrind返回值就能夠知道哪些測試用例Valgrind報告了錯誤。
--show-below-main=<yes|no> [default: no]
默認地,錯誤時的棧回溯不顯示main()之下的任何函數(或者相似的函數像glibc的__libc_start_main(),若是main()沒有出如今棧回溯中);這些大部分都是使人厭倦的C庫函數。若是打開這個選項,在main()之下的函數也將會顯示。
--suppressions=<filename> [default: $PREFIX/lib/valgrind/default.supp]
指定一個額外的文件讀取不須要理會的錯誤;你能夠根據須要使用任意多的額外文件。
--gen-suppressions=<yes|no|all> [default: no]
當設置爲yes時,Valgrind將會在每一個錯誤顯示以後自動暫停而且打印下面這一行:---- Print suppression ? --- [Return/N/n/Y/y/C/c] ----這個提示的行爲和--db-attach選項(見下面)相同。若是選擇是,Valgrind會打印出一個錯誤的禁止條目,你能夠把它剪切而後粘帖到一個文件,若是不但願在未來再看到這個錯誤信息。當設置爲all時,Valgrind會對每個錯誤打印一條禁止條目,而不向用戶詢問。這個選項對C++程序很是有用,它打印出編譯器調整過的名字。注意打印出來的禁止條目是儘量的特定的。若是須要把相似的條目概括起來,好比在函數名中添加通配符。而且,有些時候兩個不一樣的錯誤也會產生一樣的禁止條目,這時Valgrind就會輸出禁止條目不止一次,可是在禁止條目的文件中只須要一份拷貝(可是若是多於一份也不會引發什麼問題)。而且,禁止條目的名字像<在這兒輸入一個禁止條目的名字>;名字並非很重要,它只是和-v選項一塊兒使用打印出全部使用的禁止條目記錄。
--db-attach=<yes|no> [default: no]
當這個選項打開時,Valgrind將會在每次打印錯誤時暫停並打出以下一行:---- Attach to debugger ? --- [Return/N/n/Y/y/C/c] ---- 按下回車,或者N、回車,n、回車,Valgrind不會對這個錯誤啓動調試器。按下Y、回車,或者y、回車,Valgrind會啓動調試器並設定在程序運行的這個點。當調試結束時,退出,程序會繼續運行。在調試器內部嘗試繼續運行程序,將不會生效。按下C、回車,或者c、回車,Valgrind不會啓動一個調試器,而且不會再次詢問。注意:--db-attach=yes與--trace-children=yes有衝突。你不能同時使用它們。Valgrind在這種狀況下不能啓動。
2002.05: 這是一個歷史的遺留物,若是這個問題影響到你,請發送郵件並投訴這個問題。
2002.11:若是你發送輸出到日誌文件或者到網絡端口,我猜這不會讓你有任何感受。不須理會。
--db-command=<command> [default: gdb -nw %f %p]
經過--db-attach指定如何使用調試器。默認的調試器是gdb.默認的選項是一個運行時擴展Valgrind的模板。 %f會用可執行文件的文件名替換,%p會被可執行文件的進程ID替換。
這指定了Valgrind將怎樣調用調試器。默認選項不會由於在構造時是否檢測到了GDB而改變,一般是/usr/bin/gdb.使用這個命令,你能夠指定一些調用其它的調試器來替換。
給出的這個命令字串能夠包括一個或多個%p %f擴展。每個%p實例都被解釋成將調試的進程的PID,每個%f實例都被解釋成要調試的進程的可執行文件路徑。
--input-fd=<number> [default: 0, stdin]
使用--db-attach=yes和--gen-suppressions=yes選項,在發現錯誤時,Valgrind會停下來去讀取鍵盤輸入。默認地,從標準輸入讀取,因此關閉了標準輸入的程序會有問題。這個選項容許你指定一個文件描述符來替代標準輸入讀取。
--max-stackframe=<number> [default: 2000000]
棧的最大值。若是棧指針的偏移超過這個數量,Valgrind則會認爲程序是切換到了另一個棧執行。若是在程序中有大量的棧分配的數組,你可能須要使用這個選項。valgrind保持對程序棧指針的追蹤。若是棧指針的偏移超過了這個數量,Valgrind假定你的程序切換到了另一個棧,而且Memcheck行爲與棧指
針的偏移沒有超出這個數量將會不一樣。一般這種機制運轉得很好。然而,若是你的程序在棧上申請了大的結構,這種機制將會表現得愚蠢,而且Memcheck將會報告大量的非法棧內存訪問。這個選項容許把這個閥值設置爲其它值。應該只在Valgrind的調試輸出中顯示須要這麼作時才使用這個選項。在這種狀況下,它會告訴你應該指定的新的閥值。廣泛地,在棧中分配大塊的內存是一個壞的主意。由於這很容易用光你的棧空間,尤爲是在內存受限的系統或者支持大量小堆棧的線程的系統上,由於Memcheck執行的錯誤檢查,對於堆上的數據比對棧上的數據要高效不少。若是你使用這個選項,你可能但願考慮重寫代碼在堆上分配內存而不是在棧上分配。
MALLOC()相關的選項:
對於使用自有版本的malloc() (例如Memcheck和massif),下面的選項可使用。
--alignment=<number> [default: 8]
默認Valgrind的malloc(),realloc(), 等等,是8字節對齊地址的。這是大部分處理器的標準。然而,一些程序可能假定malloc()等老是返回16字節或更多對齊的內存。提供的數值必須在8和4096區間以內,而且必須是2的冪數。
非通用選項:
這些選項能夠用於全部的工具,它們影響Valgrind core的幾個特性。大部分人不會用到這些選項。
--run-libc-freeres=<yes|no> [default: yes]
GNU C庫(libc.so),全部程序共用的,可能會分配一部份內存自已用。一般在程序退出時釋放內存並不麻煩 -- 這裏沒什麼問題,由於Linux內核在一個進程退出時會回收進程所有的資源,因此這只是會形成速度慢。glibc的做者認識到這樣會致使內存檢查器,像Valgrind,在退出時檢查內存錯誤的報告glibc的內存泄漏問題,爲了不這個問題,他們提供了一個__libc_freeres()例程特別用來讓glibc釋放分配的全部內存。所以Memcheck在退出時嘗試着去運行__libc_freeres()。不幸的是,在glibc的一些版本中,__libc_freeres是有bug會致使段錯誤的。這在Red Hat 7.1上有特別聲明。因此,提供這個選項來決定是否運行__libc_freeres。若是你的程序看起來在Valgrind上運行得很好,可是在退出時發生段錯誤,你可能須要指定--run-libc-freeres=no來修正,這將可能錯誤的報告libc.so的內存泄漏。
--sim-hints=hint1,hint2,...
傳遞雜湊的提示給Valgrind,輕微的修改模擬行爲的非標準或危險方式,可能有助於模擬奇怪的特性。默認沒有提示打開。當心使用!目前已知的提示有:
l lax-ioctls: 對ioctl的處理很是不嚴格,惟一的假定是大小是正確的。不須要在寫時緩衝區徹底的初始化。沒有這個,用大量的奇怪的ioctl命令來使用一些設備驅動將會很是煩人。
l enable-inner:打開某些特殊的效果,當運行的程序是Valgrind自身時。
--kernel-variant=variant1,variant2,...
處理系統調用和ioctls在這個平臺的默認核心上產生不一樣的變量。這有助於運行在改進過的內核或者支持非標準的ioctls上。當心使用。若是你不理解這個選項作的是什麼那你幾乎不須要它。已經知道的變量有:
l bproc: 支持X86平臺上的sys_broc系統調用。這是爲了運行在BProc,它是標準Linux的一個變種,有時用來構建集羣。
--show-emwarns=<yes|no> [default: no]
當這個選項打開時,Valgrind在一些特定的狀況下將對CPU仿真產生警告。一般這些都是不引人注意的。
--smc-check=<none|stack|all> [default: stack]
這個選項控制Valgrind對自我修改的代碼的檢測。Valgrind能夠不作檢測,能夠檢測棧中自我修改的代碼,或者任意地方檢測自我修改的代碼。注意默認選項是捕捉絕大多數狀況,到目前咱們瞭解的狀況爲止。使用all選項時會極大的下降速度。(可是用none選項運行極少影響速度,由於對大多數程序,很是少的代碼被添加到棧中)
調試VALGRIND選項:
還有一些選項是用來調試Valgrind自身的。在運行通常的東西時不該該須要的。若是你但願看到選項列表,使用--help-debug選項。
內存檢查選項:
--leak-check=<no|summary|yes|full> [default: summary]
當這個選項打開時,當客戶程序結束時查找內存泄漏。內存泄漏意味着有用malloc分配內存塊,可是沒有用free釋放,並且沒有指針指向這塊內存。這樣的內存塊永遠不能被程序釋放,由於沒有指針指向它們。若是設置爲summary,Valgrind會報告有多少內存泄漏發生了。若是設置爲full或yes,Valgrind給出每個獨立的泄漏的詳細信息。
--show-reachable=<yes|no> [default: no]
當這個選項關閉時,內存泄漏檢測器只顯示沒有指針指向的內存塊,或者只能找到指向塊中間的指針。當這個選項打開時,內存泄漏檢測器還報告有指針指向的內存塊。這些塊是最有可能出現內存泄漏的地方。你的程序可能,至少在原則上,應該在退出前釋放這些內存塊。這些有指針指向的內存塊和沒有指針指向的內存塊,或者只有內部指針指向的塊,均可能產生內存泄漏,由於實際上沒有一個指向塊起始的指針能夠拿來釋放,即便你想去釋放它。
--leak-resolution=<low|med|high> [default: low]
在作內存泄漏檢查時,肯定memcheck將怎麼樣考慮不一樣的棧是相同的狀況。當設置爲low時,只須要前兩層棧匹配就認爲是相同的狀況;當設置爲med,必需要四層棧匹配,當設置爲high時,全部層次的棧都必須匹配。對於hardcore內存泄漏檢查,你極可能須要使用--leak-resolution=high和--num-callers=40或者更大的數字。注意這將產生巨量的信息,這就是爲何默認選項是四個調用者匹配和低分辨率的匹配。注意--leak-resolution= 設置並不影響memcheck查找內存泄漏的能力。它只是改變告終果如何輸出。
--freelist-vol=<number> [default: 5000000]
當客戶程序使用free(C中)或者delete(C++)釋放內存時,這些內存並非立刻就能夠用來再分配的。這些內存將被標記爲不可訪問的,並被放到一個已釋放內存的隊列中。這樣作的目的是,使釋放的內存再次被利用的點儘量的晚。這有利於memcheck在內存塊釋放後這段重要的時間檢查對塊不合法的訪問。這個選項指定了隊列所能容納的內存總容量,以字節爲單位。默認的值是5000000字節。增大這個數目會增長memcheck使用的內存,但同時也增長了對已釋放內存的非法使用的檢測機率。
--workaround-gcc296-bugs=<yes|no> [default: no]
當這個選項打開時,假定讀寫棧指針如下的一小段距離是gcc 2.96的bug,而且不報告爲錯誤。距離默認爲256字節。注意gcc 2.96是一些比較老的Linux發行版(RedHat 7.X)的默認編譯器,因此你可能須要使用這個選項。若是不是必要請不要使用這個選項,它可能會使一些真正的錯誤溜掉。一個更好的解決辦法是使用較新的,修正了這個bug的gcc/g++版本。
--partial-loads-ok=<yes|no> [default: no]
控制memcheck如何處理從地址讀取時字長度,字對齊,所以哪些字節是能夠尋址的,哪些是不能夠尋址的。當設置爲yes是,這樣的讀取並不拋出一個尋址錯誤。而是從非法地址讀取的V字節顯示爲未定義,訪問合法地址仍然是像日常同樣映射到內存。設置爲no時,從部分錯誤的地址讀取與從徹底錯誤的地址讀取一樣處理:拋出一個非法地址錯誤,結果的V字節顯示爲合法數據。注意這種代碼行爲是違背ISO C/C++標準,應該被認爲是有問題的。若是可能,這種代碼應該修正。這個選項應該只是作爲一個最後考慮的方法。
--undef-value-errors=<yes|no> [default: yes]
控制memcheck是否檢查未定義值的危險使用。當設爲yes時,Memcheck的行爲像Addrcheck, 一個輕量級的內存檢查工具,是Valgrind的一個部分,它並不檢查未定義值的錯誤。使用這個選項,若是你不但願看到未定義值錯誤。
CACHEGRIND選項:
手動指定I1/D1/L2緩衝配置,大小是用字節表示的。這三個必須用逗號隔開,中間沒有空格,例如: valgrind --tool=cachegrind --I1=65535,2,64你能夠指定一個,兩個或三個I1/D1/L2緩衝。若是沒有手動指定,每一個級別使用普通方式(經過CPUID指令獲得緩衝配置,若是失敗,使用默認值)獲得的配置。
--I1=<size>,<associativity>,<line size>
指定第一級指令緩衝的大小,關聯度和行大小。
--D1=<size>,<associativity>,<line size>
指定第一級數據緩衝的大小,關聯度和行大小。
--L2=<size>,<associativity>,<line size>
指定第二級緩衝的大小,關聯度和行大小。
CALLGRIND選項:
--heap=<yes|no> [default: yes]
當這個選項打開時,詳細的追蹤堆的使用狀況。關閉這個選項時,massif.pid.txt或massif.pid.html將會很是的簡短。
--heap-admin=<number> [default: 8]
每一個塊使用的管理字節數。這隻能使用一個平均的估計值,由於它可能變化。glibc使用的分配器每塊須要4~15字節,依賴於各方面的因素。管理已經釋放的塊也須要空間,儘管massif不計算這些。
--stacks=<yes|no> [default: yes]
當打開時,在剖析信息中包含棧信息。多線程的程序可能有多個棧。
--depth=<number> [default: 3]
詳細的堆信息中調用過程的深度。增長這個值能夠給出更多的信息,可是massif會更使這個程序運行得慢,使用更多的內存,而且產生一個大的massif.pid.txt或者massif.pid.hp文件。
--alloc-fn=<name>
指定一個分配內存的函數。這對於使用malloc()的包裝函數是有用的,能夠用它來填充原來無效的上下文信息。(這些函數會給出無用的上下文信息,並在圖中給出無心義的區域)。指定的函數在上下文中被忽略,例如,像對malloc()同樣處理。這個選項能夠在命令行中重複屢次,指定多個函數。
--format=<text|html> [default: text]
產生text或者HTML格式的詳細堆信息,文件的後綴名使用.txt或者.html。
HELGRIND選項:
--private-stacks=<yes|no> [default: no]
假定線程棧是私有的。
--show-last-access=<yes|some|no> [default: no]
顯示最後一次字訪問出錯的位置。
LACKEY選項:
--fnname=<name> [default: _dl_runtime_resolve()]
對<name>函數計數。
--detailed-counts=<no|yes> [default: no]
對讀取,存儲和alu操做計數。