Valgrind介紹(一)

用C/C++開發(fā)其中最令人頭疼的一個問題就是內(nèi)存管理荸镊,有時候為了查找一個內(nèi)存泄漏或者一個內(nèi)存訪問越界拜马,需要要花上好幾天時間单芜,如果有一款工具能夠幫助我們做這件事情就好了展姐,valgrind正好就是這樣的一款工具躁垛。

Valgrind是一款基于模擬linux下的程序調(diào)試器和剖析器的軟件套件,可以運行于x86, amd64和ppc32架構(gòu)上圾笨。valgrind包含一個核心教馆,它提供一個虛擬的CPU運行程序,還有一系列的工具擂达,它們完成調(diào)試土铺,剖析和一些類似的任務(wù)。valgrind是高度模塊化的,所以開發(fā)人員或者用戶可以給它添加新的工具而不會損壞己有的結(jié)構(gòu)悲敷。

valgrind的官方網(wǎng)址是:http://valgrind.org

你可以在它的網(wǎng)站上下載到最新的valgrind究恤,它是開放源碼和免費的。

一后德、介紹

valgrind包含幾個標準的工具部宿,它們是:

1、memcheck

memcheck探測程序中內(nèi)存管理存在的問題瓢湃。它檢查所有對內(nèi)存的讀/寫操作理张,并截取所有的malloc/new/free/delete調(diào)用。因此memcheck工具能夠探測到以下問題:

1)使用未初始化的內(nèi)存

2)讀/寫已經(jīng)被釋放的內(nèi)存

3)讀/寫內(nèi)存越界

4)讀/寫不恰當(dāng)?shù)膬?nèi)存椣浼荆空間

5)內(nèi)存泄漏

6)使用malloc/new/new[]和free/delete/delete[]不匹配涯穷。

2棍掐、cachegrind

cachegrind是一個cache剖析器藏雏。它模擬執(zhí)行CPU中的L1, D1和L2 cache,因此它能很精確的指出代碼中的cache未命中作煌。如果你需要掘殴,它可以打印出cache未命中的次數(shù),內(nèi)存引用和發(fā)生cache未命中的每一行代碼粟誓,每一個函數(shù)奏寨,每一個模塊和整個程序的摘要。如果你要求更細致的信息鹰服,它可以打印出每一行機器碼的未命中次數(shù)病瞳。在x86和amd64上,cachegrind通過CPUID自動探測機器的cache配置悲酷,所以在多數(shù)情況下它不再需要更多的配置信息了套菜。

3、helgrind

helgrind查找多線程程序中的競爭數(shù)據(jù)设易。helgrind查找內(nèi)存地址逗柴,那些被多于一條線程訪問的內(nèi)存地址,但是沒有使用一致的鎖就會被查出顿肺。這表示這些地址在多線程間訪問的時候沒有進行同步戏溺,很可能會引起很難查找的時序問題。

二屠尊、valgrind對你的程序都做了些什么

valgrind被設(shè)計成非侵入式的旷祸,它直接工作于可執(zhí)行文件上,因此在檢查前不需要重新編譯讼昆、連接和修改你的程序托享。要檢查一個程序很簡單,只需要執(zhí)行下面的命令就可以了

valgrind --tool=tool_name program_name

比如我們要對ls -l命令做內(nèi)存檢查,只需要執(zhí)行下面的命令就可以了

valgrind --tool=memcheck ls -l

不管是使用哪個工具嫌吠,valgrind在開始之前總會先取得對你的程序的控制權(quán)止潘,從可執(zhí)行關(guān)聯(lián)庫里讀取調(diào)試信息。然后在valgrind核心提供的虛擬CPU上運行程序辫诅,valgrind會根據(jù)選擇的工具來處理代碼凭戴,該工具會向代碼中加入檢測代碼,并把這些代碼作為最終代碼返回給valgrind核心炕矮,最后valgrind核心運行這些代碼么夫。

如果要檢查內(nèi)存泄漏,只需要增加--leak-check=yes就可以了肤视,命令如下

valgrind --tool=memcheck --leak-check=yes ls -l

不同工具間加入的代碼變化非常的大档痪。在每個作用域的末尾,memcheck加入代碼檢查每一片內(nèi)存的訪問和進行值計算邢滑,代碼大小至少增加12倍腐螟,運行速度要比平時慢25到50倍。

valgrind模擬程序中的每一條指令執(zhí)行困后,因此乐纸,檢查工具和剖析工具不僅僅是對你的應(yīng)用程序,還有對共享庫摇予,GNU C庫汽绢,X的客戶端庫都起作用。

三侧戴、現(xiàn)在開始

首先宁昭,在編譯程序的時候打開調(diào)試模式(gcc編譯器的-g選項)。如果沒有調(diào)試信息酗宋,即使最好的valgrind工具也將中能夠猜測特定的代碼是屬于哪一個函數(shù)积仗。打開調(diào)試選項進行編譯后再用valgrind檢查,valgrind將會給你的個詳細的報告本缠,比如哪一行代碼出現(xiàn)了內(nèi)存泄漏斥扛。

當(dāng)檢查的是C++程序的時候,還應(yīng)該考慮另一個選項 -fno-inline丹锹。它使得函數(shù)調(diào)用鏈很清晰稀颁,這樣可以減少你在瀏覽大型C++程序時的混亂。比如在使用這個選項的時候楣黍,用memcheck檢查openoffice就很容易匾灶。當(dāng)然,你可能不會做這項工作租漂,但是使用這一選項使得valgrind生成更精確的錯誤報告和減少混亂阶女。

一些編譯優(yōu)化選項(比如-O2或者更高的優(yōu)化選項)颊糜,可能會使得memcheck提交錯誤的未初始化報告,因此秃踩,為了使得valgrind的報告更精確衬鱼,在編譯的時候最好不要使用優(yōu)化選項。

如果程序是通過腳本啟動的憔杨,可以修改腳本里啟動程序的代碼鸟赫,或者使用--trace-children=yes選項來運行腳本。

下面是用memcheck檢查ls -l命令的輸出報告消别,在終端下執(zhí)行下面的命令

valgrind --tool=memcheck ls -l

程序會打印出ls -l命令的結(jié)果抛蚤,最后是valgrind的檢查報告如下:

==4187==

==4187== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 19 from 2)

==4187== malloc/free: in use at exit: 15,154 bytes in 105 blocks.

==4187== malloc/free: 310 allocs, 205 frees, 60,093 bytes allocated.

==4187== For counts of detected errors, rerun with: -v

==4187== searching for pointers to 105 not-freed blocks.

==4187== checked 145,292 bytes.

==4187==

==4187== LEAK SUMMARY:

==4187== definitely lost: 0 bytes in 0 blocks.

==4187== possibly lost: 0 bytes in 0 blocks.

==4187== still reachable: 15,154 bytes in 105 blocks.

==4187== suppressed: 0 bytes in 0 blocks.

==4187== Reachable blocks (those to which a pointer was found) are not shown.

==4187== To see them, rerun with: --show-reachable=yes

這里的“4187”指的是執(zhí)行l(wèi)s -l的進程ID,這有利于區(qū)別不同進程的報告寻狂。memcheck會給出報告岁经,分配置和釋放了多少內(nèi)存,有多少內(nèi)存泄漏了蛇券,還有多少內(nèi)存的訪問是可達的缀壤,檢查了多少字節(jié)的內(nèi)存。

下面舉兩個用valgrind做內(nèi)存檢查的例子

例子一 (test.c):

#include <string.h>

int main(int argc, char *argv[])

{

? ? char *ptr;

? ? ptr = (char*) malloc(10);

? ? strcpy(ptr, "01234567890");

? ? return 0;

}

編譯程序

gcc -g -o test test.c

用valgrind執(zhí)行命令

valgrind --tool=memcheck --leak-check=yes ./test

報告如下

==4270== Memcheck, a memory error detector.

==4270== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.

==4270== Using LibVEX rev 1606, a library for dynamic binary translation.

==4270== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.

==4270== Using valgrind-3.2.0, a dynamic binary instrumentation framework.

==4270== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.

==4270== For more details, rerun with: -v

==4270==

==4270== Invalid write of size 1

==4270== at 0x4006190: strcpy (mc_replace_strmem.c:271)

==4270== by 0x80483DB: main (test.c:8)

==4270== Address 0x4023032 is 0 bytes after a block of size 10 alloc'd

==4270== at 0x40044F6: malloc (vg_replace_malloc.c:149)

==4270== by 0x80483C5: main (test.c:7)

==4270==

==4270== Invalid write of size 1

==4270== at 0x400619C: strcpy (mc_replace_strmem.c:271)

==4270== by 0x80483DB: main (test.c:8)

==4270== Address 0x4023033 is 1 bytes after a block of size 10 alloc'd

==4270== at 0x40044F6: malloc (vg_replace_malloc.c:149)

==4270== by 0x80483C5: main (test.c:7)

==4270==

==4270== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 12 from 1)

==4270== malloc/free: in use at exit: 10 bytes in 1 blocks.

==4270== malloc/free: 1 allocs, 0 frees, 10 bytes allocated.

==4270== For counts of detected errors, rerun with: -v

==4270== searching for pointers to 1 not-freed blocks.

==4270== checked 51,496 bytes.

==4270==

==4270==

==4270== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1

==4270== at 0x40044F6: malloc (vg_replace_malloc.c:149)

==4270== by 0x80483C5: main (test.c:7)

==4270==

==4270== LEAK SUMMARY:

==4270== definitely lost: 10 bytes in 1 blocks.

==4270== possibly lost: 0 bytes in 0 blocks.

==4270== still reachable: 0 bytes in 0 blocks.

==4270== suppressed: 0 bytes in 0 blocks.

==4270== Reachable blocks (those to which a pointer was found) are not shown.

==4270== To see them, rerun with: --show-reachable=yes

從這份報告可以看出怀读,進程號是4270诉位,test.c的第8行寫內(nèi)存越界了,引起寫內(nèi)存越界的是strcpy函數(shù)菜枷,

第7行泄漏了10個字節(jié)的內(nèi)存,引起內(nèi)存泄漏的是malloc函數(shù)叁丧。

例子二(test2.c)

#include <stdio.h>

int foo(int x)

{

? ? if (x < 0) {

? ? ? ? printf("%d ", x);

? ? }

? ? return 0;

}

int main(int argc, char *argv[])

{

? ? int x;


? ? foo(x);

? ? return 0;

}

編譯程序

gcc -g -o test2 test2.c

用valgrind做內(nèi)存檢查

valgrind --tool=memcheck ./test2

輸出報告如下

==4285== Memcheck, a memory error detector.

==4285== Copyright (C) 2002-2006, and GNU GPL'd, by Julian Seward et al.

==4285== Using LibVEX rev 1606, a library for dynamic binary translation.

==4285== Copyright (C) 2004-2006, and GNU GPL'd, by OpenWorks LLP.

==4285== Using valgrind-3.2.0, a dynamic binary instrumentation framework.

==4285== Copyright (C) 2000-2006, and GNU GPL'd, by Julian Seward et al.

==4285== For more details, rerun with: -v

==4285==

==4285== Conditional jump or move depends on uninitialised value(s)

==4285== at 0x8048372: foo (test2.c:5)

==4285== by 0x80483B4: main (test2.c:16)

==4285==p p

==4285== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 12 from 1)

==4285== malloc/free: in use at exit: 0 bytes in 0 blocks.

==4285== malloc/free: 0 allocs, 0 frees, 0 bytes allocated.

==4285== For counts of detected errors, rerun with: -v

==4285== All heap blocks were freed -- no leaks are possible.

從這份報告可以看出進程PID是4285啤誊,test2.c文件的第16行調(diào)用了foo函數(shù),在test2.c文件的第5行foo函數(shù)使用了一個未初始化的變量拥娄。

valgrind還有很多使用選項蚊锹,具體可以查看valgrind的man手冊頁和valgrind官方網(wǎng)站的在線文檔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末稚瘾,一起剝皮案震驚了整個濱河市牡昆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌摊欠,老刑警劉巖丢烘,帶你破解...
    沈念sama閱讀 222,681評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異些椒,居然都是意外死亡播瞳,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,205評論 3 399
  • 文/潘曉璐 我一進店門免糕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來赢乓,“玉大人忧侧,你說我怎么就攤上這事∨朴螅” “怎么了蚓炬?”我有些...
    開封第一講書人閱讀 169,421評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長躺屁。 經(jīng)常有香客問我试吁,道長,這世上最難降的妖魔是什么楼咳? 我笑而不...
    開封第一講書人閱讀 60,114評論 1 300
  • 正文 為了忘掉前任熄捍,我火速辦了婚禮,結(jié)果婚禮上母怜,老公的妹妹穿的比我還像新娘余耽。我一直安慰自己,他們只是感情好苹熏,可當(dāng)我...
    茶點故事閱讀 69,116評論 6 398
  • 文/花漫 我一把揭開白布碟贾。 她就那樣靜靜地躺著,像睡著了一般轨域。 火紅的嫁衣襯著肌膚如雪袱耽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,713評論 1 312
  • 那天干发,我揣著相機與錄音朱巨,去河邊找鬼。 笑死枉长,一個胖子當(dāng)著我的面吹牛冀续,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播必峰,決...
    沈念sama閱讀 41,170評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼洪唐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吼蚁?” 一聲冷哼從身側(cè)響起凭需,我...
    開封第一講書人閱讀 40,116評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肝匆,沒想到半個月后粒蜈,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,651評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡术唬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,714評論 3 342
  • 正文 我和宋清朗相戀三年薪伏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片粗仓。...
    茶點故事閱讀 40,865評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡嫁怀,死狀恐怖设捐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情塘淑,我是刑警寧澤萝招,帶...
    沈念sama閱讀 36,527評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站存捺,受9級特大地震影響槐沼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捌治,卻給世界環(huán)境...
    茶點故事閱讀 42,211評論 3 336
  • 文/蒙蒙 一岗钩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧肖油,春花似錦兼吓、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,699評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至县袱,卻和暖如春浑娜,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背式散。 一陣腳步聲響...
    開封第一講書人閱讀 33,814評論 1 274
  • 我被黑心中介騙來泰國打工筋遭, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人杂数。 一個月前我還...
    沈念sama閱讀 49,299評論 3 379
  • 正文 我出身青樓宛畦,卻偏偏與公主長得像,于是被迫代替她去往敵國和親揍移。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,870評論 2 361