Linux下記憶體洩漏定位常用工具介紹
寫在前面:
本人只是一個linux開發新手,對linux下開發充滿熱情,前段時間接手一個linux下程式效能優化的工作,自己在整個過程中零零散散的總結了一些經驗,特別把查詢和定位記憶體洩漏方面的經驗寫下來,尤其是使用的幾個開源工具,希望對別人有用,也等於自己做做筆記,便於以後再次使用或學習。
整個過程主要有以下幾個方面:
1、閱讀原始碼及分析動態記憶體的使用
由於之前沒有做過類似的問題(純屬小白了,慘遭鄙視....),所以就想著通過自己去看程式碼,查詢裡面涉及到使用動態記憶體的程式碼段去定位問題(現在想想,真是太幼稚了,大家見笑了...),但是自己還是去通過對原始碼跟蹤、分析,主要是對動態分配的記憶體(如malloc函式分配的記憶體)、一些檔案描述符等進行跟蹤,分析在程式邏輯中對動態分配的記憶體有沒有手動進行釋放,開啟的檔案描述符有沒有關閉等這些程式碼一點點的去分析,當然這也是熟悉程式碼,瞭解的一個過程。
2、利用memwatch記憶體檢測工具對程式進行記憶體分析
Memwatch是一款C語言的記憶體檢測工具。memwatch使用它自己定義的功能函式取代所有在你的程式中用ANSI C定義的記憶體分配函式,memwatch的記憶體分配函式包含了所有的分配記錄資訊。memwatch功能預設不是開啟的,除非定義了MEMWATCH,否則在程式碼中不會跟蹤相關的記憶體使用情況。memwatch通常將它的資料寫入到memwatch.log檔案中,它也可以被重定向。
工具使用方法:
(2) 將memwatch.c和memwatch.h檔案拷貝到自己的工程目錄中,並在工程中的每個.c檔案中新增memwatch.h標頭檔案
(3) 利用gun工具鏈編譯時帶上選項-DMEMWATCH及-DMW_STDIO,並將memwatch.c一併編譯。例如工程檔案為test.c,需要對其進行記憶體檢測時可以如下進行編譯:
gcc -o -DMEMWATCH -DMW_STDIOtest.c memwatch.c
(4) 執行編譯好的可執行程式,有關記憶體使用資訊日誌檔案就會儲存在memwatch.log中。
優點:memwatch使用簡單方便,工具本身佔用記憶體少。
缺點:功能簡單,不能檢測出所有程式中存在的記憶體問題,可能會有遺漏。在我實踐過程中,使用memwatch就不能檢測出程式呼叫開源庫函式時發生記憶體洩漏的問題,memwatch只能做簡單的記憶體檢測。
3、利用valgrind記憶體檢測工具分析記憶體
Valgrind是執行在Linux上的一套基於模擬技術的程式除錯和分析工具,它包含一個核心,一個軟體合成的CPU,和一系列的小工具,每個工具都可以完成一項任務──除錯,分析,或測試等。Valgrind可以檢測記憶體洩漏和記憶體違例,還可以分析cache的使用等,靈活輕巧而又強大。
Valgrind一般包含下列工具:
(1) memcheck
最常用的工具,用來檢測程式中出現的記憶體問題,所有對記憶體的讀寫都會被檢測到,一切對malloc()/free()/new/delete的呼叫都會被捕獲。所以,它能檢測以下問題:
a.對未初始化記憶體的使用;
b.讀/寫釋放後的記憶體塊;
c.讀/寫超出malloc分配的記憶體塊;
d.讀/寫不適當的棧中記憶體塊;
e.記憶體洩漏,指向一塊記憶體的指標永遠丟失;
f.不正確的malloc/free或new/delete匹配;
g,memcpy()相關函式中的dst和src指標重疊。
這些問題往往是C/C++程式設計師最頭疼的問題,Memcheck在這裡幫上了大忙。
(2) Callgrind
和gprof類似的分析工具,但它對程式的執行觀察更是入微,能給我們提供更多的資訊。
(3) Cachegrind
Cache分析器,它模擬CPU中的一級快取I1,Dl和二級快取,能夠精確地指出程式中cache的丟失和命中。
(4) Helgrind
它主要用來檢查多執行緒程式中出現的競爭問題。Helgrind尋找記憶體中被多個執行緒訪問,而又沒有一貫加鎖的區域,這些區域往往是執行緒之間失去同步的地方,而且會導致難以發掘的錯誤。
(5) Massif
堆疊分析器,它能測量程式在堆疊中使用了多少記憶體,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少記憶體的使用,在帶有虛擬記憶體的現代系統中,它還能夠加速我們程式的執行,減少程式停留在交換區中的機率。
Valgrind工具使用方法:
(2) 按照工具要求安裝Valgrind工具
(3) 待工具安裝完成後,使用valgrind來執行程式即可,舉例如下:
如編譯好的工程檔案為memleak,則使用valgrind執行memleak如下:
valgrind [options] ./memleak
通常使用到的選項有:--tool=memcheck (指定工具)
--leak-check=full(設定檢測所有記憶體問題)
--show-leak-kinds=all(設定提示所有記憶體洩漏問題)
--track-origins=yes
--log-file=valgrind.log(設定檢測的日誌資訊文字)
--track-fds=yes(設定檢測檔案描述符)
--time-stamp=yes(設定在日誌檔案中加入時間戳)
valgrind結果分析:記憶體洩露. Memcheck將記憶體洩露分為兩種,一種是可能的記憶體洩露(Possibly lost),另外一種是確定的記憶體洩露(Definitely lost)。Possibly lost 是指仍然存在某個指標能夠訪問某塊記憶體,但該指標指向的已經不是該記憶體首地址。Definitely lost 是指已經不能夠訪問這塊記憶體。而Definitely lost又分為兩種:直接的(direct)和間接的(indirect)。直接和間接的區別就是,直接是沒有任何指標指向該記憶體,間接是指指向該記憶體的 指標都位於記憶體洩露處。
舉例如下:
valgrind --tool=memcheck --leak-check=full --show-leak-kinds=all--log-file=valgrind.log --time-stamp=yes ./memleak
優點:功能強力,使用靈活,較memwatch工具全面,可以檢測出各種記憶體問題。
缺點:使用複雜一些,需要安裝,使用時會佔用較大的記憶體。以上就先把總結寫一下,之後再慢慢將檢測的結果做一個事例貼程式碼出來!感謝大家關注!