C/C++由于靈活、高效的優點一直以來都是主流的程式設計語言之一,但是其記憶體的配置設定與釋放均由程式員自己管理,當由于疏忽或錯誤造成程式未能釋放不再使用的記憶體時就會造成記憶體洩漏。在大型、複雜的應用程式中,記憶體洩漏往往是最常見的問題,因而及時解決記憶體洩漏非常必要。tMemMonitor (TMM)作為一個專業、準确、易用的記憶體洩漏分析工具,可以幫助C/C++程式員迅速地解決記憶體洩漏這個令人頭疼的問題。
一.背景
目前市面上已有一些Windows平台下的記憶體洩漏動态檢測工具,比如UMDH,VLD,Purify,BoundsCheck等,其中Purify和BoundsCheck是昂貴的商用軟體,UMDH需要人工擷取記憶體快照,操作門檻較高,VLD則需要修改源程式的代碼,同時這幾款工具都存在誤報情況,是以準确性不高。針對Windows平台,C/C++程式員迫切需要一款專業、準确、易用的記憶體洩漏分析工具。
二.TMM簡介
TMM是一款運作時C/C++記憶體洩漏檢測工具。TMM認為在程序退出時,堆記憶體中沒有被釋放且沒有指針指向的無主記憶體塊即為記憶體洩漏,并進而引入垃圾回收(GC, Garbage Collection)機制,在程序退出時檢測出堆記憶體中所有沒有被引用的記憶體單元,因而記憶體洩露檢測準确率為100%。
TMM工具主要包含兩部分,第一部分是用戶端的檢測界面,用戶端部分主要負責監控目标程序中的記憶體行為并計算記憶體洩漏。檢測時隻要将被檢測程式添加到監控清單中,然後正常運作被檢程式即可,以下為用戶端界面:

另一部分是結果的展示與分析。TMM支援本地檢視和線上查詢兩種方式。本地檢視時,提供按洩漏次數或洩漏大小對結果進行排序的功能,并在安裝目錄的data檔案夾中給出詳細分析報告。使用者也可憑QQ帳号登入WeTest網站對記憶體洩漏情況進行線上查詢。以下為本地檢視結果:
三.TMM的特性和優點
專業
Ø 最快的注入技術
Ø 基于GC的精準算法,無需記憶體快照
Ø 無損目标程式性能
Ø 檢測結果精準定位到代碼堆棧資訊
準确
Ø 二次周遊堆記憶體對象裡的指針
Ø 寄存器級的問題跟蹤,完整掃描每個線程裡32位寄存器内的指針
Ø 不放過全局資料區裡的内容
易用
Ø 支援自定義程式
Ø 無須編譯,立即使用
Ø 一鍵操作,無需切換
四.算法原理
1. 替換/注入堆記憶體配置設定函數的算法
Windows中有多種級别的記憶體配置設定函數,其中,最底層的是ntdll.dll提供的Rtl系列函數,在這之上的有Windows API提供的heap管理函數,再上層,C/C++庫提供了malloc/free函數和new/delete操作符,是以替換如此層級複雜的函數比較困難,同時如果替換現有的堆配置設定函數,則無法做到和原有函數的執行效果完全一緻,是以替換原生的堆配置設定函數對于Windows系統來說幾乎是不可行的,那麼隻能wrap(包裹)這些堆配置設定函數。
Linux下的記憶體檢測工具,比如Valgrind就采用了包裹堆配置設定函數的方法,但它包裹的方法是不透明的,在調用棧中會多出額外一幀。TMM則采用全透明的包裹函數,将挂鈎函數分為前後二部分(如圖1所示)。在函數調用前執行per-hook函數,在函數傳回前調用執行post-hook函數。有了前後挂鈎函數,TMM就可以在堆配置設定/釋放函數執行前獲得參數,并修改配置設定大小之類的參數;在函數執行後,記錄配置設定的大小和位址、調用棧之類的資訊。
圖1
2. 洩露檢測的算法
TMM使用基于堆記憶體可通路性的記憶體洩露檢測法( reachability-based leak detection),該算法的核心就是檢測(掃描)沒有任何指針指向的堆記憶體,具體分為五步:
Step 1. 程序退出時,suspend所有線程,防止資料在掃描過程中更改。假設此時程序中的堆記憶體布局如圖2所示;
圖2
Step 2. 統計root-set,它由每個線程的寄存器、所有非堆記憶體、所有線程棧幀頂部RSP/ESP以上區域、所有庫的資料區組成;
Step 3. 從root-set出發周遊圖2,标記出有指針指向的記憶體塊,即beginning reachable blocks,如圖3中A、C;
圖3
Step 4. 由于beginning reachable blocks也會包含有指針,是以通過周遊beginning reachable blocks可以找出其内部指針指向的記憶體塊并标記,如圖4中B;
圖4
Step 5. 統計檢測出來的記憶體洩漏,即圖4中unreachable的堆記憶體塊D、E、F。
五.使用步驟
圖5
1. 在擁有Administrator權限的情況下啟動TMM。
2. 在監控清單中右鍵添加目标程式,正常操作。
3. 正常退出目标程式。
4. 耐心等待檢測結果生成(目标程式狀态由running變為null時,說明程式正常退出,檢測結果生成完畢)。
5. 檢視結果。
六.注意事項
1. 安裝TMM時,使用者應具有Administrator權限,并且TMM不支援中文安裝路徑。
2. 使用TMM時需要修改系統資料庫,如遇安全軟體彈窗警告,可将TMM加入信任清單放心使用。
3. 被檢測程式不能是加殼版本,因為加殼程式的函數名和函數位址已經混淆。
4. 被檢測程式需是release版本。
5. 如需在分析報告中顯示洩漏點詳細堆棧資訊,請在被檢測程式同級目錄放置同版本的PDB檔案,PDB解析時目錄不支援中文。
6. 使用TMM導緻被測程式退出時變慢屬于正常情況,此時TMM正在統計記憶體洩漏情況,請不要手動強制結束程序。
七.總結
TMM适用于PC端所有C/C++程式的記憶體洩漏分析。對于被測程式,不需要修改源代碼,運作一次被測程式就能夠準确定位洩漏的檔案名和行号。TMM是一款專業、準确、易用的記憶體洩漏檢測工具,值得每個程式員擁有。
QQ支援: 2304186838
聯系Email: [email protected]