1. 程式人生 > >C++記憶體洩露檢查工具

C++記憶體洩露檢查工具

Linux下編寫C或者C++程式,有很多工具,但是主要編譯器仍然是gcc和g++。最近用到STL中的List程式設計,為了檢測寫的程式碼是否會發現記憶體洩漏,瞭解了一下相關的知識。

所有使用動態記憶體分配(dynamic memory allocation)的程式都有機會遇上記憶體洩露(memory leakage)問題,在Linux裡有三種常用工具來檢測記憶體洩露的情況,包括:

工具 描述
一個強大開源的程式檢測工具
GNU擴充套件, 用來跟蹤malloc, mtrace為記憶體分配函式(malloc, realloc, memalign, free)安裝hook函式
用於檢查C/C++記憶體洩露(leak)的工具,即檢查是否存在直到程式執行結束還沒有釋放的記憶體,以一個執行庫的方式釋出
memwatch 和dmalloc一樣,它能檢測未釋放的記憶體、同一段記憶體被釋放多次、位址存取錯誤及不當使用未分配之記憶體區域

1 被測程式

為了方便測試,,我們編寫了一個簡單的程式, 迴圈10次每次申請了一個100個位元組的單元, 但是卻不釋放

2 valgrind

2.1 valgrind介紹

是不是說沒有一種記憶體檢查工具能夠在Linux使用呢,也不是,像開源的valgrind工具還是相當不錯的

  • Memcheck。這是valgrind應用最廣泛的工具,一個重量級的記憶體檢查器,能夠發現開發中絕大多數記憶體錯誤使用情況,比如:使用未初始化的記憶體,使用已經釋放了的記憶體,記憶體訪問越界等。這也是本文將重點介紹的部分。

  • Callgrind。它主要用來檢查程式中函式呼叫過程中出現的問題。

  • Cachegrind。它主要用來檢查程式中快取使用出現的問題。

  • Helgrind。它主要用來檢查多執行緒程式中出現的競爭問題。

  • Massif。它主要用來檢查程式中堆疊使用中出現的問題。

  • Extension。可以利用core提供的功能,自己編寫特定的記憶體除錯工具

valgrind介紹

2.2 安裝

原始碼安裝

下載地址)下載最新版的valgrind,按照裡面的README提示,安裝後就可以使用這個工具來檢測記憶體洩露和記憶體越界等

/configure

make

sudo make install
  • 1
  • 2
  • 3
  • 4
  • 5

當然也可以使用發行版的自帶的源中安裝

sudo apt install valgrind
  • 1

這是一個沒有介面的記憶體檢測工具,安裝後,輸入 valgrind ls -l 驗證一下該工具是否工作正常(這是README裡面的方法,實際上是驗證一下對ls -l命令的記憶體檢測),如果你看到一堆的資訊說明你的工具可以使用了。

2.3 使用說明

Valgrind工具包包含多個工具,如Memcheck,Cachegrind,Helgrind, Callgrind,Massif。

Memcheck

最常用的工具,用來檢測程式中出現的記憶體問題,所有對記憶體的讀寫都會被檢測到,一切對malloc()/free()/new/delete的呼叫都會被捕獲。所以,Memcheck 工具主要檢查下面的程式錯誤

內容 描述
使用未初始化的記憶體 Use of uninitialised memory
使用已經釋放了的記憶體 Reading/writing memory after it has been free’d
使用超過 malloc分配的記憶體空間 Reading/writing off the end of malloc’d blocks
對堆疊的非法訪問 Reading/writing inappropriate areas on the stack
申請的空間是否有釋放 Memory leaks – where pointers to malloc’d blocks are lost forever
malloc/free/new/delete申請和釋放記憶體的匹配 Mismatched use of malloc/new/new [] vs free/delete/delete []
src和dst的重疊 Overlapping src and dst pointers in memcpy() and related functions

這些問題往往是C/C++程式設計師最頭疼的問題,Memcheck在這裡幫上了大忙。

Callgrind

和gprof類似的分析工具,但它對程式的執行觀察更是入微,能給我們提供更多的資訊。和gprof不同,它不需要在編譯原始碼時附加特殊選項,但加上除錯選項是推薦的。Callgrind收集程式執行時的一些資料,建立函式呼叫關係圖,還可以有選擇地進行cache模擬。在執行結束時,它會把分析資料寫入一個檔案。callgrind_annotate可以把這個檔案的內容轉化成可讀的形式。

Cachegrind

Cache分析器,它模擬CPU中的一級快取I1,Dl和二級快取,能夠精確地指出程式中cache的丟失和命中。如果需要,它還能夠為我們提供cache丟失次數,記憶體引用次數,以及每行程式碼,每個函式,每個模組,整個程式產生的指令數。這對優化程式有很大的幫助。

Helgrind

它主要用來檢查多執行緒程式中出現的競爭問題。Helgrind尋找記憶體中被多個執行緒訪問,而又沒有一貫加鎖的區域,這些區域往往是執行緒之間失去同步的地方,而且會導致難以發掘的錯誤。Helgrind實現了名為“Eraser”的競爭檢測演算法,並做了進一步改進,減少了報告錯誤的次數。不過,Helgrind仍然處於實驗階段。

Massif

堆疊分析器,它能測量程式在堆疊中使用了多少記憶體,告訴我們堆塊,堆管理塊和棧的大小。Massif能幫助我們減少記憶體的使用,在帶有虛擬記憶體的現代系統中,它還能夠加速我們程式的執行,減少程式停留在交換區中的機率。

此外,lackey和nulgrind也會提供。Lackey是小型工具,很少用到;Nulgrind只是為開發者展示如何建立一個工具

注意

Valgrind不檢查靜態分配陣列的使用情況

Valgrind佔用了更多的記憶體–可達兩倍於你程式的正常使用量

如果你用Valgrind來檢測使用大量記憶體的程式就會遇到問題,它可能會用很長的時間來執行測試

2.4 使用說明

編譯程式

g++ -g -o leak leak.c 
  • 1

被檢測程式加入 –g -fno-inline 編譯選項保留除錯資訊, 否則後面的valgrind不能顯示到出錯行號。

valgrind被設計成非侵入式的,它直接工作於可執行檔案上,因此在檢查前不需要重新編譯、連線和修改你的程式。要檢查一個程式很簡單,只需要執行下面的命令就可以了。

valgrind --tool=tool_name program_name
  • 1

比如我們要對ls -l命令做記憶體檢查,只需要執行下面的命令就可以了

valgrind --tool=memcheck ls -l
  • 1

小提示 
如果不知道有哪些引數, 可以先輸入valgrind –tool=, 然後狂按兩次tab, 會輸出linux系統的只能提示, 同樣,如果你輸入了valgrind –tool=mem再狂按兩次tab,linux系統會為你自動補全

2.5 使用valgrind檢測Memcheck

下面我們就可以用valgrind對我們的程式檢測leak

valgrind --tool=memcheck --leak-check=full --show-reachable=yes --trace-children=yes    ./leak
  • 1

其中–leak-check=full 指的是完全檢查記憶體洩漏,

–show-reachable=yes是顯示記憶體洩漏的地點,

–trace-children=yes是跟入子程序。

當程式正常退出的時候valgrind自然會輸出記憶體洩漏的資訊原理:

輸出記憶體洩漏的資訊原

3 mtrace檢測記憶體洩露

3.1 mtrace簡介

在一般的linux發行版中,有一個自帶的工具可以很方便的替你完成這些事,這個工具就是mtrace.

mtrace其實是GNU擴充套件函式,用來跟蹤malloc。

mtrace為記憶體分配函式(malloc, realloc, memalign, free)安裝hook函式。這些hook函式記錄記憶體的申請和釋放的trace資訊。 
在程式中,這些trace資訊可以被用來發現記憶體洩漏和釋放不是申請的記憶體。 
當呼叫mtrace,mtrace會檢查環境變數MALLOC_TRACE。該環境變數應該包含記錄trace資訊的檔案路徑。如果檔案可以被成功開啟,它的大小被截斷為0。 
如果MALLOC_TRACE沒有設定,或者設定的檔案不可用或者不可寫,那麼將不會安裝hook函式,mtrace不生效。

詳細說明可參考man page:man 3 mtrace

3.2 mtrace使用

mtrace能監測程式是否記憶體洩露

  • 在程式的起始處包含標頭檔案
#include <mcheck.h>
  • 1
  • 更改環境變數:export MALLOC_TRACE=”mtrace.out”可以加入如下程式碼
setenv("MALLOC_TRACE", "mtrace.out", 1);
  • 1
  • 呼叫函式mtrace()
mtrace()
  • 1
  • 編譯程式帶上 -g 選項
gcc -g -c leak_mtrace.c -o leak_mtrace.o  -std=gnu9x -Wall
  • 1
  • 執行程式一次,儘量呼叫所有程式內的函式。這時除錯資訊就已經被寫入我們指定的mtrace.out檔案中
./leak_mtrace 
  • 1
  • mtrace a.out mtrace.out檢視記憶體監測情況
mtrace a.out  mtrace.out
  • 1

這裡寫圖片描述

4 dmalloc

dmalloc是一種用於檢查C/C++記憶體洩露(leak)的工具,即檢查是否存在直到程式執行結束還沒有釋放的記憶體,並且能夠精確指出在哪個原始檔的第幾行。

5 Linux核心的Kmemleak

5.1 Kmemleak檢測工具介紹

Kmemleak工作於核心態是核心自帶的核心洩露檢測工具, 其原始碼位於mm/kmemleak.c

Kmemleak工作於核心態,Kmemleak 提供了一種可選的核心洩漏檢測,其方法類似於跟蹤記憶體收集器。當獨立的物件沒有被釋放時,其報告記錄在 /sys/kernel/debug/kmemleak中,Kmemcheck能夠幫助定位大多數記憶體錯誤的上下文。

5.2 Kmemleak使用過程概述

  • 首先`CONFIG_DEBUG_KMEMLEAK在Kernel hacking中被使能.

  • 檢視核心列印資訊詳細過程如下:

    1. 掛載debugfs檔案系統 
      mount -t debugfs nodev /sys/kernel/debug/
    2. 開啟核心自動檢測執行緒 
      echo scan > /sys/kernel/debug/kmemleak
    3. 檢視列印資訊 
      cat /sys/kernel/debug/kmemleak
    4. 清除核心檢測報告,新的記憶體洩露報告將重新寫入/sys/kernel/debug/kmemleak 
      echo clear > /sys/kernel/debug/kmemleak

記憶體掃描引數可以進行修改通過向/sys/kernel/debug/kmemleak 檔案寫入。 引數使用如下

off 禁用kmemleak(不可逆)
stack=on 啟用任務堆疊掃描(default)
stack=off 禁用任務堆疊掃描
scan=on 啟動自動記憶掃描執行緒(default)
scan=off 停止自動記憶掃描執行緒
scan=<secs> 設定n秒內自動記憶掃描
scan 開啟核心掃描
clear 清除記憶體洩露報告
dump=<addr> 轉存資訊物件在<addr>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

通過“kmemleak = OFF”,也可以在啟動時禁用Kmemleak在核心命令列。在初始化kmemleak之前,記憶體的分配或釋放這些動作被儲存在一個前期日誌緩衝區。這個緩衝區的大小通過配CONFIG_DEBUG_KMEMLEAK_EARLY_LOG_SIZE設定。

5.3 Kmemleak動態檢測原理

通過的kmalloc、vmalloc、kmem_cache_alloc等記憶體分配會跟蹤其指標,連同其他的分配大小和堆疊跟蹤資訊,儲存在PRIO搜尋樹。相應的釋放函式呼叫跟蹤和指標就會從kmemleak資料結構中移除。 
分配的記憶體塊,被認為是獨立的,如果沒有指標指向它起始地址或塊的內部的任何位置,可以發現掃描記憶體(包括已儲存的暫存器)。這意味著,有可能沒有辦法為核心通過所分配的地址傳遞塊到一個釋放函式,因此,該塊被認為是一個記憶體洩漏。

掃描演算法步驟: 
1. 標記的所有分配物件為白色(稍後將剩餘的白色物體考慮獨立的)

  1. 掃描儲存器與所述資料片段和棧開始,檢查對地址的值儲存在PRIO搜尋樹。如果一個白色的物件的指標被發現,該物件將被新增到灰名單

  2. 掃描的灰色物件匹配的地址(一些白色物體可以變成灰色,並新增結束時的灰名單),直到黑色集結束

  3. 剩下的白色物體被認為是獨立兒,並報告寫入/sys/kernel/debug/kmemleak。 
    一些分配的記憶體塊的指標在核心的內部資料結構和它們不能被檢測為孤兒。對避免這種情況,kmemleak也可以儲存的數量的值,指向一個內的塊的地址範圍內的地址,需要找到使塊不被認為是洩漏.

5.4 kmem相關函式

從kernel原始碼中的目錄include /linux/kmemleak.h中可檢視函式原型的頭

函式 功能
kmemleak_init 初始化kmemleak
kmemleak_alloc 一個記憶體塊分配的通知
kmemleak_alloc_percpu 通知的一個percpu的記憶體塊分配
kmemleak_free 通知的記憶體塊釋放
kmemleak_free_part 通知釋放部分記憶體塊
kmemleak_free_percpu 一個percpu記憶體塊釋放的通知
kmemleak_not_leak 當不是洩露時,標記物件
kmemleak_ignore 當洩漏時不掃描或報告物件
kmemleak_scan_area 新增掃描區域內的記憶體塊
kmemleak_no_scan 不掃描的記憶體塊
kmemleak_erase 刪除一個指標變數的舊值
kmemleak_alloc_recursive 為kmemleak_alloc,只檢查遞迴
kmemleak_free_recursive 為kmemleak_free,只檢查遞迴

相關推薦

C++記憶體洩露檢查工具

Linux下編寫C或者C++程式,有很多工具,但是主要編譯器仍然是gcc和g++。最近用到STL中的List程式設計,為了檢測寫的程式碼是否會發現記憶體洩漏,瞭解了一下相關的知識。 所有使用動態記憶體分配(dynamic memory allocation)的程式都有機

VC記憶體洩露檢查工具:VisualLeakDetector

轉自 http://www.xdowns.com/article/170/Article_3060.html 初識Visual Leak Detector        靈活自由是C/C++語言的一大特色,而這也為C/C++程式設計師出了一個難題

c記憶體洩漏檢查工具---mtrace

    專案中出現記憶體洩漏是讓人很頭疼的事情,使用了vargrind效果不明顯,可能因為試用了libuv裡面有太多非同步處理,導致使用vargrind會出現段錯誤。後來發現mtrace,使用還是挺簡單的。     mtrace是gn

Visual C++ 記憶體洩露檢測工具(VLD)

簡述 C/C++ 程式越複雜,記憶體的管理顯得越重要,稍有不慎就會出現洩漏。如果記憶體洩漏不是很嚴重,在短時間內對程式不會有太大影響,這也使得記憶體洩漏問題有很強的隱蔽性,不易被發現。然而不管記憶體洩漏多麼輕微,當程式長時間執行時,其破壞力是驚人的 - 從效能

Windows/Linux下C/C++記憶體洩露檢測工具

一 Window下的記憶體洩露檢測(以VC++環境為例) 靈活自由是C語言的一大特色,但這個特色也難以避免的帶來一些副作用,比如記憶體洩露。眾所周知,記憶體洩露的問題比較複雜,程式正常執行時你看不出它有任何異常,但長時間執行或在特定條件下特定操作重複多次時,它才暴露出來。所

Mac下C++記憶體洩露檢測工具

1) nvwa(寓意女媧補天,從sourceforge下載),直接將其程式碼編譯到工程中,發現有洩露後程序即終止; nvwa能夠檢測到記憶體洩露問題,但是試用後感覺不穩定 2) leaks命令,能確

使用Visual Leak Detector for Visual C++ 捕捉記憶體洩露---Visual C++記憶體洩露檢測—VLD工具使用說明

以下經過測試: 使用Visual Leak Detector for Visual C++ 捕捉記憶體洩露 1、下載vlc 2、建立應用並配置 c/c++ -> General -> Additional Include Directories = C:\P

Linux C 程式設計記憶體洩露檢測工具(二):memwatch

Memwatch簡介 在三種檢測工具當中,設定最簡單的算是memwatch,和dmalloc一樣,它能檢測未釋放的記憶體、同一段記憶體被釋放多次、位址存取錯誤及不當使用未分配之記憶體區域。請往http://www.linkdata.se/sourcecode.html下載最

Visual C++記憶體洩露檢測—VLD工具使用說明d

轉自:http://www.cnblogs.com/lidabo/archive/2012/07/19/2599745.html http://blog.csdn.net/zlQQhs/article/details/10039179 1.VLD工具概述 Visual

c++記憶體洩漏檢測工具(上)

原文連結: http://blog.csdn.net/beanjoy/article/details/7578372   1/  VC自帶的CRT:_CrtCheckMemory   偵錯程式和 CRT 除錯堆函式 用法 /********

C 記憶體洩漏檢測工具

所有使用動態記憶體分配(dynamic memory allocation)的程式都有機會遇上記憶體洩露(memory leakage)問題,在Linux裡有三種常用工具來檢測記憶體洩露的情況,包括: mtrace dmalloc memwatch 1. mtrace

linux下記憶體洩露檢測工具Valgrind介紹

一、工作中一個記憶體洩漏問題的解決過程: 問題背景:我司裝置上執行有多個程序,在裝置執行兩天後,程序jsman所佔用的記憶體達到了1200M bytes(通過ps -aux檢視)。 解決步驟: 確定裝置上的軟體版本,根據git的commit號資訊回退

CC++記憶體問題檢查利器——Purify

C/C++記憶體問題檢查利器——Purify 一、           引言   我們都知道軟體的測試(在以產品為主的軟體公司中叫做QA—Quality Assessm

Windows平臺下如何檢測C/C++記憶體洩露

對於C/C++程式設計師來說,效率和優雅性大多數情況是對立的,我們經常會在這裡面抉擇,到底應該怎麼取捨。而說到效率,就不得不說讓這類程式設計師頭疼了N年的問題,記憶體洩露,至少從C/C++發明以來很多人都在頭疼。而Java/C#之類的語言並不存在這種問題,因為他們從堆中申請記憶體,根據引用計數等(據說有六種方

精準 iOS 記憶體洩露檢測工具----MLeaksFinder

背景 平常我們都會用 Instrument 的 Leaks / Allocations 或其他一些開源庫進行記憶體洩露的排查,但它們都存在各種問題和不便,我們逐個來看這些工具的使用和存在的問題。 Leaks 先看看 Leaks,從蘋果的開發者文件裡可以看到,一個 app 的記憶體分三類:

c++記憶體洩露檢測

// 以下程式碼在vs2013上面測試#include <stdlib.h> #include <crtdbg.h> // 在入口函式中包含 _CrtDumpMemoryLeaks(); // 即可檢測到記憶體洩露 typedef void* HObjec

Android studio記憶體洩露分析工具使用

什麼是記憶體洩漏 Android虛擬機器的垃圾回收採用的是根搜尋演算法。GC會從根節點(GC Roots)開始對heap進行遍歷。到最後,部分沒有直接或者間接引用到GC Roots的就是需要回收的垃圾,會被GC回收掉。而記憶體洩漏出現的原因就是存在了無

MemoryAnalyzer-記憶體洩露分析工具

概述 對於大型 JAVA 應用程式來說,再精細的測試也難以堵住所有的漏洞,即便我們在測試階段進行了大量卓有成效的工作,很多問題還是會在生產環境下暴露出來,並且很難在測試環境中進行重現。JVM 能夠記錄下問題發生時系統的部分執行狀態,並將其儲存在堆轉儲 (Heap Dump) 檔案中,從而為我們分析和診斷

Android記憶體洩露分析工具—Android Monitor

記憶體洩露大家應該不會陌生了,通常是因為該被釋放的物件被佔用,不能及時對其釋放,導致GC無法正常回收。我們可以使用一些工具來監控和分析導致記憶體洩露的位置和原因。用Eclipse的同志應該都知道MAT(Memory Analysis Tools),Android

Android記憶體洩露檢測工具和實際開發中遇到的記憶體洩露問題解析

介紹 記憶體洩露是平常開發中經常遇到的,有些時候稍不注意就會發生,而且還不易察覺,這就需要工具來幫助檢測。本文主要介紹記憶體檢測工具和我在開發中遇到的記憶體洩露問題和解決方案。 記憶體洩露的原理 具體的原理涉及到虛擬機器垃圾回收機制知識,這裡只為下文作