http://www.cnblogs.com/napoleon_liu/articles/2001802.html
調不盡的記憶體洩漏,用不完的Valgrind
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工具)(可選)
6. ./configure;配置Valgrind,生成MakeFile檔案,具體參數資訊詳見INSTALL檔案。一般隻需要設定--prefix=/where/you/want/it/installed
7. Make;編譯Valgrind
8. make install;安裝Valgrind
Valgrind包含的工具
Valgrind支援很多工具:memcheck,addrcheck,cachegrind,Massif,helgrind和Callgrind等。在運作Valgrind時,你必須指明想用的工具,如果省略工具名,預設運作memcheck。
1、memcheck
memcheck探測程式中記憶體管理存在的問題。它檢查所有對記憶體的讀/寫操作,并截取所有的malloc/new/free/delete調用。是以memcheck工具能夠探測到以下問題:
1)使用未初始化的記憶體
2)讀/寫已經被釋放的記憶體
3)讀/寫記憶體越界
4)讀/寫不恰當的記憶體棧空間
5)記憶體洩漏
6)使用malloc/new/new[]和free/delete/delete[]不比對。
7)src和dst的重疊
2、cachegrind
cachegrind是一個cache剖析器。它模拟執行CPU中的L1, D1和L2 cache,是以它能很精确的指出代碼中的cache未命中。如果你需要,它可以列印出cache未命中的次數,記憶體引用和發生cache未命中的每一行代碼,每一個函數,每一個子產品和整個程式的摘要。如果你要求更細緻的資訊,它可以列印出每一行機器碼的未命中次數。在x86和amd64上, cachegrind通過CPUID自動探測機器的cache配置,是以在多數情況下它不再需要更多的配置資訊了。
3、helgrind
helgrind查找多線程程式中的競争資料。helgrind查找記憶體位址,那些被多于一條線程通路的記憶體位址,但是沒有使用一緻的鎖就會被查出。這表示這些位址在多線程間通路的時候沒有進行同步,很可能會引起很難查找的時序問題。
它主要用來檢查多線程程式中出現的競争問題。Helgrind 尋找記憶體中被多個線程通路,而又沒有一貫加鎖的區域,這些區域往往是線程之間失去同步的地方,而且會導緻難以發掘的錯誤。Helgrind實作了名為”Eraser” 的競争檢測算法,并做了進一步改進,減少了報告錯誤的次數。
4、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
5、Massif
堆棧分析器,它能測量程式在堆棧中使用了多少記憶體,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少記憶體的使用,在帶有虛拟記憶體的現代系統中,它還能夠加速我們程式的運作,減少程式停留在交換區中的幾率。
6、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]=’’;
strcpy(x,x+20); //Good
x[39]=40;
x[40]=’’;
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操作計數。