3. C++內(nèi)存泄露掃描利器--valgrind

一. 簡述valgrind是什么,為何能進(jìn)行內(nèi)存泄露

valgrind是一個(gè)程序調(diào)試及性能分析的工具集唱矛,涵蓋memcheck, cachegrind,helgrind,callgrind署驻,啟動valgrind時(shí)通過--tool來指定具體要調(diào)用的工具严卖。不論使用哪個(gè)工具全庸,通過valgrind來啟動程序時(shí)都會取得對程序的控制權(quán)靶端,從關(guān)聯(lián)庫中讀取調(diào)試信息。然后在valgrind核心提供的虛擬CPU上運(yùn)行程序藤韵,根據(jù)選擇的工具處理代碼虐沥,該工具會向代碼中植入檢測代碼,并把這些代碼作為最終代碼返回給valgrind核心,最后valgrind核心運(yùn)行這些代碼欲险。

我們最常用valgrind進(jìn)行內(nèi)存泄露檢查镐依,通過--tool = memcheck --leak-check=yes指定。需要注意的是天试,memcheck會加入代碼檢查每一片內(nèi)存的訪問和進(jìn)行值運(yùn)算槐壳,導(dǎo)致整體代碼大小至少增加12倍,運(yùn)行速度比平時(shí)慢25-50倍喜每,所以使用valgrind時(shí)务唐,保證機(jī)器環(huán)境有足夠多的內(nèi)存,如果進(jìn)程本身啟動內(nèi)存有十幾G带兜,那用valgrind啟動程序時(shí)枫笛,一般啟動特別慢,可能1h才能啟動程序刚照⌒糖桑或者,valgrind根本就拉不起來程序无畔,此時(shí)啊楚,需要修改程序的相關(guān)配置參數(shù),想辦法將程序啟動的進(jìn)程內(nèi)存減小浑彰。

二.編譯程序時(shí)的注意

1. 編譯時(shí)恭理,打開調(diào)試模式(gcc編譯器的-g選項(xiàng))。

2. 編譯時(shí)闸昨,關(guān)閉編譯優(yōu)化選項(xiàng)蚯斯。一些編譯優(yōu)化選項(xiàng)(比如-O2或者更高的優(yōu)化選項(xiàng)),可能會使得memcheck提交錯(cuò)誤的未初始化報(bào)告饵较,因此拍嵌,為了使得valgrind的報(bào)告更精確,在編譯的時(shí)候最好不要使用優(yōu)化選項(xiàng)循诉。

3. 如果程序有對tcmalloc編譯依賴的話横辆,需要將tcmalloc從編譯依賴中去掉,否則valgrind掃描可能會遺漏一些報(bào)警信息茄猫。

4. 當(dāng)檢查的是C++程序的時(shí)候狈蚤,還應(yīng)該考慮另一個(gè)選項(xiàng) -fno-inline。它使得函數(shù)調(diào)用鏈很清晰划纽,這樣可以減少你在瀏覽大型C++程序時(shí)的混亂脆侮。比如在使用這個(gè)選項(xiàng)的時(shí)候,用memcheck檢查openoffice就很容易勇劣。當(dāng)然靖避,你可能不會做這項(xiàng)工作潭枣,但是使用這一選項(xiàng)使得valgrind生成更精確的錯(cuò)誤報(bào)告和減少混亂。

三. valgrind下載 & 安裝

---> 下載:wget?http://www.valgrind.org/downloads/valgrind-3.8.1.tar.bz2

目前最新的版本是:Release 3.12.0 20 October 2016

---> 解壓:bzip2 -d valgrind-3.8.1.tar.bz2; tar -xvf valgrind-3.8.1.tar

---> 安裝: cd valgrind-3.8.1; ./configure --prefix=/home/work/tools/valgrind-3.8.1.install;make;make install

安裝好后在valgrind-3.8.1.install目錄里有: bin, lib, include, share 4個(gè)子目錄

---> 確認(rèn)是否安裝正確:valgrind --version

---> 編輯/etc/profile幻捏,將valgrind工具加入PATH盆犁,再source /etc/profile,這樣每次使用時(shí)都是新安裝的valgrind

四篡九、valgrind memcheck選項(xiàng)

參見手冊http://www.valgrind.org/docs/manual/mc-manual.html

valgrind的選項(xiàng)非常的多谐岁,可以參考翻譯手冊中的說明進(jìn)行選用,下面列出幾個(gè)比較常用的:

Option :--leak-check=no|summary|full|yes? [default summary]

Purpose : 當(dāng)這個(gè)選項(xiàng)打開時(shí)榛臼,會當(dāng)客戶程序結(jié)束時(shí)查找內(nèi)存泄露伊佃。如果設(shè)置為summary,Valgrind會報(bào)告有多少內(nèi)存泄露發(fā)生了讽坏。如果設(shè)置為full或yes锭魔,Valgrind給出每一個(gè)獨(dú)立的泄露的詳細(xì)信息例证。

Option :--leak-resolution=high|med|low ?[default low]

Purpose :在做內(nèi)存泄漏檢查時(shí)路呜,確定memcheck將怎么樣考慮不同的棧是相同的情況。當(dāng)設(shè)置為low時(shí)织咧,只需要前兩層棧匹配就認(rèn)為是相同的情況胀葱;當(dāng)設(shè)置為med,必須要四層棧匹配笙蒙,當(dāng)設(shè)置為high時(shí)抵屿,所有層次的棧都必須匹配。

注意--leak-resolution= 設(shè)置并不影響memcheck查找內(nèi)存泄漏的能力捅位。它只是改變了結(jié)果如何輸出轧葛。

Option: --show-reachable=yes|no ?[default no]

Purpose : 當(dāng)這個(gè)選項(xiàng)關(guān)閉時(shí),內(nèi)存泄露檢測器只顯示沒有指針指向的內(nèi)存塊艇搀,或者只能找到指向塊中間的指針尿扯。當(dāng)這個(gè)選項(xiàng)打開時(shí),內(nèi)存泄露檢測器還報(bào)告有指針指向的內(nèi)存塊焰雕。這些塊是最有可能出現(xiàn)內(nèi)存泄露的地方衷笋。你的程序可能,至少在原則上矩屁,應(yīng)該在退出前釋放這些內(nèi)存塊辟宗。這些有指針指向的內(nèi)存塊和沒有指針指向的內(nèi)存塊,或者只有內(nèi)部指針指向的塊吝秕,都可能產(chǎn)生內(nèi)存泄露泊脐,因?yàn)閷?shí)際上沒有一個(gè)指向塊起始的指針可以拿來釋放,即使你想去釋放它烁峭。

Option: -v

Purpose : 顯示詳細(xì)信息容客。在各個(gè)方面顯示你的程序的額外信息,例如:共享對象加載,使用的重置耘柱,執(zhí)行引擎和工具的進(jìn)程如捅,異常行為的警告信息。重復(fù)這個(gè)標(biāo)記可以增加詳細(xì)的級別调煎。

Option : -fno-inline

Purpose : 當(dāng)檢查的是C++程序的時(shí)候镜遣,可考慮這個(gè)選項(xiàng)-fno-inline。它使得函數(shù)調(diào)用鏈很清晰

Option : --max-stackframe=[default: 2000000]

Purpose : 棧的最大值士袄,默認(rèn)2000000悲关。如果棧指針的偏移超過這個(gè)數(shù)量,valgrind則會認(rèn)為程序是切換到了另外一個(gè)棧執(zhí)行娄柳。

五. 內(nèi)存泄露掃描過程

---> 程序啟動(如果程序本身內(nèi)存十幾個(gè)G寓辱,啟動非常慢,可能1h多才啟動):

?nohup valgrind--tool=memcheck --leak-check=full --show-reachable=yes

--max-stackframe=8000000 --log-file=./valgrind.log [程序啟動命令] &

---> 判斷程序是否啟動成功:

搜索程序端口是否被監(jiān)聽來判斷程序是否被valgrind拉起

netstat -anlp|grep 9600|grep LISTEN ? ##如果進(jìn)程名是valgrind赤拒,則表示程序已經(jīng)在valgrind環(huán)境中啟動成功秫筏。

---> 給程序放一些請求,請求盡可能覆蓋到程序的各個(gè)分支

---> 程序優(yōu)雅退出挎挖,不要讓服務(wù)在valgrind環(huán)境里core掉了这敬。盡量服務(wù)有捕獲kill信號能力,一般kill -9 pid會導(dǎo)致服務(wù)core掉蕉朵。

---> 退出等待個(gè)幾分鐘崔涂,讓valgrind收集退出信息輸出到valgrind.log。最后分析valgrind.log

六. valgrind.log 報(bào)告分析

見手冊http://www.valgrind.org/docs/manual/mc-manual.html 始衅,關(guān)注關(guān)注definitely lost和possible lost處可能的內(nèi)存泄露冷蚂。

1)首先搜關(guān)鍵字『LEAK SUMMARY』,看『definitely lost』對應(yīng)是否有值汛闸,如果不為0蝙茶,肯定有內(nèi)存泄露。

2)如果有內(nèi)存泄露蛉拙,往上搜報(bào)告中『definitely lost in loss』的報(bào)警處尸闸,對照程序代碼一一排查。

3)常見內(nèi)存泄露警告

---> a. Illegal read / Illegal write errors

已釋放后的內(nèi)存進(jìn)行讀/寫或數(shù)組的越界訪問等孕锄,valgrind報(bào)告程序在嘗試讀寫非法內(nèi)存吮廉,造成的后果是程序易發(fā)生segmentation fault(吐core)風(fēng)險(xiǎn)。

Invalid write of size X畸肆,訪問超出了范圍的內(nèi)存宦芦,試圖從該內(nèi)存讀取數(shù)據(jù)

---> b. Use of uninitialised values

檢測使用未初始化變量,可以檢測在條件判斷語句中使用未初始化變量轴脐,因此應(yīng)該養(yǎng)成在聲明變量時(shí)就進(jìn)行初始化的習(xí)慣

Conditional jump or move depends on uninitialised value(s)

---> c. When a heap block is freed with an inappropriate deallocation function

使用不正確的方法釋放內(nèi)存调卑,比如new/delete , malloc/free使用混淆了抡砂,new分配的地方用free釋放了

Mismatched free() / delete / delete []

---> d. Illegal frees

重復(fù)內(nèi)存釋放,比如2次使用free釋放同一塊內(nèi)存

Invalid free() / delete / delete[]

---> e. Overlapping source and destination blocks

針對C語言常見的memcpy, strcpy, strncpy, strcat, strncat拷貝類函數(shù)恬涧,出現(xiàn)源串和目標(biāo)串地址重疊

Source and destination overlap in memcpy(0xbffff294, 0xbffff280, 21)

---> f. Fishy argument values

所有內(nèi)存分配類函數(shù)在分配內(nèi)存時(shí)注益,都會傳入一個(gè)內(nèi)存分配大小的數(shù),如果你傳入的數(shù)大于機(jī)器所能分配的最大數(shù)時(shí)溯捆,如64位機(jī)器上丑搔,你傳入的size大于了2**63

Argument 'size' of function malloc has a fishy (possibly negative) value: -3

---> g. Leak detecion

HEAP SUMMARY: ?

如果指定--show-reachable=yes,在程序退出時(shí)memcheck會收集reachable and indirectly lost blocks

LEAK SUMMARY:

memcheck會記錄由malloc/new等函數(shù)創(chuàng)建的所有的heap blocks提揍,因此在程序退出時(shí)啤月,memcheck能夠知道哪些block沒有free。如下:

definitely lost: 4 bytes in 1 blocks

indirectly lost: 0 bytes in 0 blocks

possibly lost: 0 bytes in 0 blocks

still reachable: 95 bytes in 6 blocks

definitely lost:如果一個(gè)block在程序在退出后劳跃,memcheck找不到指向它的pointer谎仲,一般是由于在代碼中對該block沒有free造成的,要重點(diǎn)關(guān)注刨仑。

possibly lost:在程序退出時(shí)郑诺,memcheck發(fā)現(xiàn)仍有 interior pointer(如果一個(gè)pointer指向一個(gè)block的中間某個(gè)位置)指向一個(gè)block,那么該block被認(rèn)為是possibly lost贸人。

still reachable:如果memcheck發(fā)現(xiàn)仍有start pointer指向一個(gè)block间景,那么該block就是still reachable。

4)valgrind不能查出哪些錯(cuò)誤?

valgrind不對靜態(tài)數(shù)組(分配在棧上)進(jìn)行邊界檢查艺智。如果在程序中聲明了一個(gè)數(shù)組:

int main()

{

char x[10];

x[11] = ′a′;

}

valgrind則不會警告你,出于測試目的圾亏,你可以把數(shù)組改為動態(tài)在堆上分配的數(shù)組十拣,這樣就可能進(jìn)行邊界檢查了。這個(gè)方法好像有點(diǎn)得不償失的感覺志鹃。

七. 安裝或使用中踩得各種坑

1)valgrind: failed to start tool 'memcheck' for platform 'amd64-linux'

解決辦法:

該錯(cuò)誤是valgrind啟動時(shí)夭问,無法找到相關(guān)工具文件,有可能是安裝好后相關(guān)lib的path未設(shè)置曹铃,也有可能是一開始安裝就有問題缰趋。解決辦法如下:

如果已經(jīng)安裝成功,試一下導(dǎo)出VALGRIND_LIB路徑陕见,用法如下(假設(shè)valgrind已經(jīng)被安裝到/home/work/tools/valgrind目錄):##親測有效##

export VALGRIND_LIB=/home/work/tools/valgrind3.8.1/lib/valgrind

2)valgrind --version報(bào)錯(cuò)

valgrind: mmap((nil), 134512640) failed during startup.

valgrind: is there a hard virtual memory limit set?

解決辦法:

見下秘血,版本太老,里邊有bug评甜,重新安裝一下較新版本應(yīng)該能解決灰粮。https://twiki.cern.ch/twiki/bin/view/LHCb/CodeAnalysisTools

3)vg_alloc_ThreadState: no free slots available

Increase VG_N_THREADS, rebuild and try again.

valgrind: the 'impossible' happened:

VG_N_THREADS is too low

解決辦法:

a) 修改VG_N_THREADS和NTHREADS的值,安裝用的是3.8.1版本忍坷,默認(rèn)VG_N_THREADS是500粘舟,現(xiàn)在改為5000熔脂,同時(shí)NTHREADS由498改成4998。

include/pub_tool_threadstate.h: #define VG_N_THREADS 5000

./memcheck/tests/err_disable4.c: #define NTHREADS 4998 ?// VG_N_THREADS - 2

b) 按照1進(jìn)行重新安裝柑肴。

4) Valgrind: FATAL: VG_N_SEGMENTS is too low.

解決辦法:

VG_N_SEGMENTS默認(rèn)是5000霞揉。修改coregrind/m_aspacemgr/aspacemgr-linux.c: VG_N_SEGMENTS從5000改到50000,VG_N_NAME從1000改到5000晰骑。

按照1進(jìn)行重新安裝零聚。

5)valgrind.log報(bào)告中,在definitely lost的代碼處全是些侍?隶症??岗宣?蚂会?全寫花了,看不出具體泄露的是在哪一行代碼

解決辦法:

加上-g耗式,打開調(diào)試信息重新編譯程序胁住;

valgrind掃描時(shí)加上--show-reachable=yes


參考:

1. http://www.xlgps.com/article/216977.html

2. 如何使用Valgrind memcheck工具進(jìn)行C/C++的內(nèi)存泄漏檢測

3.?用Valgrind查找內(nèi)存泄漏和無效內(nèi)存訪問

4.?valgrind介紹

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刊咳,一起剝皮案震驚了整個(gè)濱河市彪见,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌娱挨,老刑警劉巖余指,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異跷坝,居然都是意外死亡酵镜,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門柴钻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來淮韭,“玉大人,你說我怎么就攤上這事贴届】糠啵” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵毫蚓,是天一觀的道長占键。 經(jīng)常有香客問我,道長绍些,這世上最難降的妖魔是什么捞慌? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮柬批,結(jié)果婚禮上啸澡,老公的妹妹穿的比我還像新娘袖订。我一直安慰自己,他們只是感情好嗅虏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布洛姑。 她就那樣靜靜地躺著,像睡著了一般皮服。 火紅的嫁衣襯著肌膚如雪楞艾。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天龄广,我揣著相機(jī)與錄音硫眯,去河邊找鬼。 笑死择同,一個(gè)胖子當(dāng)著我的面吹牛两入,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播敲才,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼裹纳,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了紧武?” 一聲冷哼從身側(cè)響起剃氧,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎阻星,沒想到半個(gè)月后朋鞍,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡迫横,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年番舆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片矾踱。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖疏哗,靈堂內(nèi)的尸體忽然破棺而出呛讲,到底是詐尸還是另有隱情,我是刑警寧澤返奉,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布贝搁,位于F島的核電站,受9級特大地震影響芽偏,放射性物質(zhì)發(fā)生泄漏雷逆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一污尉、第九天 我趴在偏房一處隱蔽的房頂上張望膀哲。 院中可真熱鬧往产,春花似錦、人聲如沸某宪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽兴喂。三九已至蔼囊,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衣迷,已是汗流浹背畏鼓。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留壶谒,地道東北人云矫。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像佃迄,于是被迫代替她去往敵國和親泼差。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容

  • linux資料總章2.1 1.0寫的不好抱歉 但是2.0已經(jīng)改了很多 但是錯(cuò)誤還是無法避免 以后資料會慢慢更新 大...
    數(shù)據(jù)革命閱讀 12,146評論 2 34
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理呵俏,服務(wù)發(fā)現(xiàn)堆缘,斷路器,智...
    卡卡羅2017閱讀 134,633評論 18 139
  • 使用MsLeak以及Instument調(diào)試解決iOS內(nèi)存泄露 雖然iOS 5.0版本之后加入了ARC機(jī)制普碎,由于相互...
    慧眾rodman閱讀 2,062評論 0 11
  • 溝通吼肥,我認(rèn)為是多方面多元化的。廣義上講麻车,溝通體現(xiàn)在生活的方方面面缀皱。閱讀,是與作者的溝通动猬。旅行啤斗,是與大自然...
    你說你傻不傻y閱讀 598評論 0 0
  • 說不清的南城舊事,道不明的北郡亂鈴赁咙。 你問我:走過了那座奈何橋钮莲,喝干了那碗孟婆湯,你還會抱著今天的執(zhí)念嗎彼水?我笑笑崔拥,...
    木木天空閱讀 125評論 0 0