Linux下用Valgrind做檢討(避免內存洩漏)。本站提示廣大學習愛好者:(Linux下用Valgrind做檢討(避免內存洩漏))文章只能為提供參考,不一定能成為您想要的結果。以下是Linux下用Valgrind做檢討(避免內存洩漏)正文
用C/C++開辟個中最使人頭疼的一個成績就是內存治理,有時刻為了查找一個內存洩露或許一個內存拜訪越界,須要要花上好幾地利間,假如有一款對象可以或許贊助我們做這件工作就行了,valgrind正好就是如許的一款對象。
Valgrind是一款基於模仿linux下的法式調試器和分析器的軟件套件,可以運轉於x86, amd64和ppc32架構上。valgrind包括一個焦點,它供給一個虛擬的CPU運轉法式,還有一系列的對象,它們完成調試,分析和一些相似的義務。valgrind是高度模塊化的,所以開辟人員或許用戶可以給它添加新的對象而不會破壞己有的構造。
valgrind的官方網址是:http://valgrind.org
你可以在它的網站高低載到最新的valgrind,它是開放源碼和收費的。
1、引見
valgrind包括幾個尺度的對象,它們是:
1、memcheck
memcheck探測法式中內存治理存在的成績。它檢討一切對內存的讀/寫操作,並截取一切的malloc/new/free/delete挪用。是以memcheck對象可以或許探測到以下成績:
1)應用未初始化的內存
2)讀/寫曾經被釋放的內存
3)讀/寫內存越界
4)讀/寫不適當的內存棧空間
5)內存洩露
6)應用malloc/new/new[]和free/delete/delete[]不婚配。
2、cachegrind
cachegrind是一個cache分析器。它模仿履行CPU中的L1, D1和L2 cache,是以它能很准確的指出代碼中的cache未射中。假如你須要,它可以打印出cache未射中的次數,內存援用和產生cache未射中的每行代碼,每個函數,每個模塊和全部法式的摘要。假如你請求更過細的信息,它可以打印出每行機械碼的未射中次數。在x86和amd64上,cachegrind經由過程CPUID主動探測機械的cache設置裝備擺設,所以在多半情形下它不再須要更多的設置裝備擺設信息了。
3、helgrind
helgrind查找多線程法式中的競爭數據。helgrind查找內存地址,那些被多於一條線程拜訪的內存地址,然則沒有應用分歧的鎖就會被查出。這表現這些地址在多線程間拜訪的時刻沒有停止同步,極可能會惹起很難查找的時序成績。
2、valgrind對你的法式都做了些甚麼
valgrind被設計成非侵入式的,它直接任務於可履行文件上,是以在檢討前不須要從新編譯、銜接和修正你的法式。要檢討一個法式很簡略,只須要履行上面的敕令便可以了
valgrind --tool=tool_name program_name
好比我們要對ls -l敕令做內存檢討,只須要履行上面的敕令便可以了
valgrind --tool=memcheck ls -l
不論是應用哪一個對象,valgrind在開端之前總會先獲得對你的法式的掌握權,從可履行聯系關系庫裡讀取調試信息。然後在valgrind焦點供給的虛擬CPU上運轉法式,valgrind會依據選擇的對象來處置代碼,該對象會向代碼中參加檢測代碼,並把這些代碼作為終究代碼前往給valgrind焦點,最初valgrind焦點運轉這些代碼。
假如要檢討內存洩露,只須要增長–leak-check=yes便可以了,敕令以下
valgrind --tool=memcheck --leak-check=yes ls -l
分歧對象間參加的代碼變更異常的年夜。在每一個感化域的末尾,memcheck參加代碼檢討每片內存的拜訪和停止值盤算,代碼年夜小至多增長12倍,運轉速度要比日常平凡慢25到50倍。
valgrind模仿法式中的每條指令履行,是以,檢討對象和分析對象不只僅是對你的運用法式,還有對同享庫,GNU C庫,X的客戶端庫都起感化。
3、如今開端
起首,在編譯法式的時刻翻開調試形式(gcc編譯器的-g選項)。假如沒有調試信息,即便最好的valgrind對象也將中可以或許猜想特定的代碼是屬於哪個函數。翻開調試選項停止編譯後再用valgrind檢討,valgrind將會給你的個具體的申報,好比哪一行代碼湧現了內存洩露。
當檢討的是C++法式的時刻,還應當斟酌另外一個選項 -fno-inline。它使得函數挪用鏈很清楚,如許可以削減你在閱讀年夜型C++法式時的凌亂。好比在應用這個選項的時刻,用memcheck檢討openoffice就很輕易。固然,你能夠不會做這項任務,然則應用這一選項使得valgrind生成更准確的毛病申報和削減凌亂。
一些編譯優化選項(好比-O2或許更高的優化選項),能夠會使得memcheck提交織誤的未初始化申報,是以,為了使得valgrind的申報更准確,在編譯的時刻最好不要應用優化選項。
假如法式是經由過程劇本啟動的,可以修正劇本裡啟動法式的代碼,或許應用–trace-children=yes選項來運轉劇本。
上面是用memcheck檢討ls -l敕令的輸入申報,在終端下履行上面的敕令
valgrind --tool=memcheck ls -l
法式會打印出ls -l敕令的成果,最初是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”指的是履行ls -l的過程ID,這有益於差別分歧過程的申報。memcheck會給出申報,分派置和釋放了若干內存,有若干內存洩露了,還有若干內存的拜訪是可達的,檢討了若干字節的內存。
上面舉兩個用valgrind做內存檢討的例子
例子一 (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履行敕令
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 0×4006190: strcpy (mc_replace_strmem.c:271)
==4270== by 0x80483DB: main (test.c:8)
==4270== Address 0×4023032 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 0×4023033 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行寫內存越界了,惹起寫內存越界的是strcpy函數,
第7行洩露了10個字節的內存,惹起內存洩露的是malloc函數。
例子二(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做內存檢討
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 0×8048372: 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行挪用了foo函數,在test2.c文件的第5行foo函數應用了一個未初始化的變量。
valgrind還有許多應用選項,詳細可以檢查valgrind的man手冊頁和valgrind官方網站的在線文檔。