關於記憶體洩露:
客戶的一台ap server,記憶體使用量一直很大,swap使用量從三月份開始在慢慢增多。懷疑與記憶體洩露有關,查詢了一些資料,發現對於linux真個系統的記憶體洩露檢測工具很少。有如下幾個,但是都只針對單個程式。如果測試真個記憶體的情況,特別是歷史記錄,不知道還有沒有好的工具。
valgrind
用c/c++開發其中最令人頭疼的乙個問題就是記憶體管理,有時候為了查詢乙個記憶體洩漏或者乙個記憶體訪問越界,需要要花上好幾天時間,如果有一款工具能夠幫助我們做這件事情就好了,valgrind正好就是這樣的一款工具。
valgrind是一款基於模擬linux下的程式偵錯程式和剖析器的軟體套件,可以執行於x86, amd64和ppc32架構上。valgrind包含乙個核心,它提供乙個虛擬的cpu執行程式,還有一系列的工具,它們完成除錯,剖析和一些類似的任務。valgrind是高度模組化的,所以開發人員或者使用者可以給它新增新的工具而不會損壞己有的結構。
一、介紹
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查詢記憶體位址,那些被多於一條執行緒訪問的記憶體位址,但是沒有使用一致的鎖就會被查出。這表示這些位址在多執行緒間訪問的時候沒有進行同步,很可能會引起很難查詢的時序問題。
二、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的客戶端庫都起作用。
三、現在開始
首先,在編譯程式的時候開啟除錯模式(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
int main(int argc, char *argv)
編譯程式
gcc -g -o test test.c
用valgrind執行命令
valgrind --tool=memcheck --leak-check=yes ./test
報告如下
從這份報告可以看出,程序號是4270,test.c的第8行寫記憶體越界了,引起寫記憶體越界的是strcpy函式,
第7行洩漏了10個位元組的記憶體,引起記憶體洩漏的是malloc函式。
例子二(test2.c)
#include
int foo(int x)
return 0;
}int main(int argc, char *argv)
編譯程式
gcc -g -o test2 test2.c
用valgrind做記憶體檢查
valgrind --tool=memcheck ./test2
輸出報告如下
從這份報告可以看出程序pid是4285,test2.c檔案的第16行呼叫了foo函式,在test2.c檔案的第5行foo函式使用了乙個未初始化的變數。
refer:
memwatch檢視linux記憶體洩露
#include
#include
#include
#include
int main()
return 0;
}編譯:gcc -dmemwatch -dmw_stdio test.c memwatch.c -o test
4. 執行結果
memwatch.log的內容如下:
Linux 記憶體洩露檢測
1.需要在記憶體洩露開始的開始呼叫void mtrace void mtrace 為malloc等函式安裝 hook,用於記錄記憶體分配資訊,在需要記憶體洩露檢查 結束的地方呼叫void muntrace void 注意 在一般情況下,不要呼叫muntrace 而讓程式自然結束。因為可能有些記憶體釋...
linux下記憶體洩露檢測
前段時間遇到一些關於記憶體方面的問題,使用了malloc stats來進行記憶體檢測。呼叫函式後,函式會把輸出定向到strerr中,內容如下,arena 0 第乙個arena 每個執行緒分配乙個arena 這裡只有乙個執行緒 system bytes 135168 本執行緒從作業系統獲得的動態記憶體...
linux 記憶體洩露檢測 mtrace
mtrace include include int main 加上標頭檔案 include 然後在main 函式的開頭加上 mtrace 在main函式返回前加上 muntrace malloc trace home stevewong mtrace mt.log export malloc tr...