使用 UMDH 之前
如果您認為您遇到內存泄漏, 應注意, 內存泄漏可能不它們似乎什么。 您可能發現內存泄漏是不滿足內存泄漏, 但是性能增強。 例如, MicrosoftJet 數據庫引擎會消耗大量內存因為它檢索數據并寫入緩存 256 - MB 計算機上 (最多 128 MB)。 緩存允許 Jet 引擎以獲得快速讀和寫提前緩沖。
要確定是否是一個進程遇到內存泄漏, 使用 Windows 性能監視器 (Perfmon.exe) 并為應用程序進程類別下監視專用字節。 專用字節是總內存, 進程已分配, 但不是與其他進程共享。 注意這是不同于 VirtualBytes, 即有趣來監視。 虛擬字節是以字節表示的虛擬地址空間, 進程使用當前大小。 應用程序可泄漏虛擬內存, 但可能沒有看到分配專用字節中差別。 如果看不到當監視專用字節, 但懷疑仍然運行用盡了內存, 增加內存監視虛擬字節以查看備份虛擬內存是否正在使用。 有關檢測內存泄漏, 附加信息請參閱以下 Microsoft Developer Network (MSDN) Web 站點上 " 查找 Leaks 和瓶頸與 WindowsNT PerfMon COM 對象 " 文章:
要確保應用程序, 是泄漏內存, 可疑代碼放在循環與許多迭代, 并然后監視對任何提高的內存和虛擬專用字節。 觀看以確保不的專用字節和虛擬字節數不最終保持相同, 并且停止數增加。 如果沒有內存增加, 停止時間點看不到內存泄漏但更可能, 到緩存, 增長至其最大尺寸 (例如, 它并不繼續到 climb 無限)。
如果您決定使用 UMDH 之前,, 您看到內存泄漏, 請按照下列步驟:
1. | 安裝 UMDH 實用程序。 |
2. | 設置要安裝 UMDH 文件夾 PATH 系統環境變量。 |
3. | 將 _ NT _ SYMBOL _ PATH 環境變量設置為 Microsoft 符號服務器路徑以便 UMDH 可以找到調試符號文件。 |
UMDH 工具是隨 DebuggingToolsforWindows 產品下面的 Microsoft Web 站點:
下載和安裝實用程序, 并將 PATH 系統環境變量到路徑其中已安裝調試工具。
使用 UMDH 之前, 必須安裝用于組成應用程序和操作系統正確調試符號。 用于 MicrosoftSymbolServer 獲取調試符號對于 Microsoft 組件。 有關 MicrosoftSymbolServer, 請單擊文章編號以查看 Microsoft 知識庫中相應:
311503 (http://support.microsoft.com/kb/311503/EN-US/) 使用 Microsoft 符號服務器來獲取調試符號文件
UMDH 嘗試通過使用 _ NT _ SYMBOL _ PATH 環境變量查找符號文件。 命令以從命令提示符設置路徑可能與以下類似:
設置 _ NT _ SYMBOL _ PATH = SRV c:\LocalSymbolCache *
其他有關設置符號調試信息, 請參閱本文中后面 " 調試符號 " 部分。
在完成這些步驟, 您就可以使用 UMDH 實用程序。
與 UMDH 轉儲捕獲堆
UMDH 是實用工具, 轉儲堆分配的進程信息。 此信息包括調用堆棧用于每個分配、 次數, 通過調用該堆棧, 進行分配和的消耗, 通過調用該堆棧字節數。 例如:
00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00053
ntdll!RtlDebugAllocateHeap+0x000000FD
ntdll!RtlAllocateHeapSlowly+0x0000005A
ntdll!RtlAllocateHeap+0x00000808
MyApp!_heap_alloc_base+0x00000069
MyApp!_heap_alloc_dbg+0x000001A2
MyApp!_nh_malloc_dbg+0x00000023
MyApp!_nh_malloc+0x00000016
MyApp!operator new+0x0000000E
MyApp!LeakyFunc+0x0000001E
MyApp!main+0x0000002C
MyApp!mainCRTStartup+0x000000FC
KERNEL32!BaseProcessStart+0x0000003D
UMDH 輸出顯示, 沒有 21280 (0x5320) 從調用堆棧分配字節總數。 從 20 21280 字節被分配單獨分配的 1064 字節 (0x428) (0 x 14)。 標識符是 BackTrace00053 提供調用堆棧。
要生成轉儲文件的堆分配, 您必須使用 Gflags.exe 實用程序, 也是隨 DebuggingToolsforWindows 產品, 來讓操作系統知道您想要跟蹤分配內核。
假設您要為 Notepad.exe 轉儲 heap(s) 內容。 必須首先啟用堆棧跟蹤獲取用于對要測試該應用程序。 默認情況下, 不啟用此功能。 要啟用此功能命令是如下: gflags notepad.exe + ust - i
命令不啟用堆棧跟蹤為進程到已經運行, 但使堆棧跟蹤對于所有將來執行是 Notepad.exe。 通過 GFLAGS 用戶界面 (不帶任何參數以獲得用戶界面運行 Gflags.exe) 或者, 您可設置標志。 使用
- ust 選項對于 gflags 以禁用堆棧跟蹤時, 調試已完成。
當您通過 Gflags.exe, 圖像標志設并且設置調試符號, 您就可以啟動記事本, 使用 UMDH (應用)。 啟動程序后, 必須確定進程 ID (PID) 的只啟動記事本進程。 對于此命令是如下:
tlist
您可以找到從輸出 TLIST 應用程序的 PID。 PID 信息也可獲得從任務管理器。 假定對于記事本過程, 您只啟動 PID 是 124。 可使用 UMDH 來獲取堆轉儲使用以下命令:
umdh - p 124 個 - f:notepad124.log:
結果 : Notepad124.log 文件中有完整堆的 Notepad 進程轉儲。 此文件顯示所有所做的分配和 callstacks 其中進行分配。
使用 umdh.exe 來比較 UMDH 日志
如果不關心查找內存泄漏, UMDH 日志文件包含對進程, 堆的當前狀態寶貴信息時可能會更重要來比較的兩個日志輸出和了解哪些調用堆棧已看到大增長兩轉儲文件之間。 Umdh.exe 實用程序幫助比較兩 UMDH 日志以提供分析之間差。 一旦有兩個日志捕獲不同間隔, 可再使用以下命令:
UMDH dh1.log dh2.log > cmp12.txt
- 或 -
UMDH -d dh1.log dh2.log > cmp12.txt
- d 命令行選項通知 UMDH 以在十進制代替十六進制顯示。 命令的輸出比較差異的分配之間兩個日志并提供是類似于以下信息:
+ 5320 (f110 - 9df0) = = 5320 3a allocs BackTrace00053 總數增加
對于每 BackTrace, UMDH 日志文件中沒有兩個日志文件之間進行比較。 本例說明最后一個日志文件 UMDH 命令行中指定有 0xF110 對于相同 BackTrace 調用 (堆棧) 分配字節分配 UMDH 命令行中第一個日志具有 0x9DF0 時字節 UMDH 命令行中第一個日志具有 0x9DF0 時分配字節對于同一 BackTrace (調用堆棧) 分配字節。 " 5320 " 是分配的字節數中差別。 此例, 沒有 0x5320 多字節時間之間分配兩日志被捕獲。 字節來自調用堆棧, 由 " BackTrace00053 "。
下一步是要了解什么是該 backtrace 中。 如果打開二日志文件和搜索
BackTrace00053 , 可能發現內容, 類似于以下內容:
00005320 bytes in 0x14 allocations (@ 0x00000428) by: BackTrace00053
ntdll!RtlDebugAllocateHeap+0x000000FD
ntdll!RtlAllocateHeapSlowly+0x0000005A
ntdll!RtlAllocateHeap+0x00000808
MyApp!_heap_alloc_base+0x00000069
MyApp!_heap_alloc_dbg+0x000001A2
MyApp!_nh_malloc_dbg+0x00000023
MyApp!_nh_malloc+0x00000016
MyApp!operator new+0x0000000E
MyApp!LeakyFunc+0x0000001E
MyApp!main+0x0000002C
MyApp!mainCRTStartup+0x000000FC
KERNEL32!BaseProcessStart+0x0000003D
當您查看調用堆棧, 您可以看到, LeakyFunc 函數分配內存通過 VisualC++ 運行時庫運算符新函數。 如果發現, 分配的數增大如采取多轉儲文件, 您可能斷定不被釋放內存。 啟用堆棧跟蹤
UMDH 日志中最重要信息是堆棧跟蹤的堆分配。 您可以分析地驗證如果進程堆內存泄漏。 默認情況下, 這些堆棧跟蹤不獲取。 您可啟用此功能每個進程或系統級。 使用以下命令以啟用堆棧跟蹤系統級:
gflags -r + ust
此命令后重新啟動計算機。 有關每個進程啟用, 命令是如下:
gflags APPNAME + ust - i
其中
APPNAME 是包括擴展名 (例如, Services.exe, Lsass.exe) 可執行的文件名。 命令不啟用堆棧跟蹤為進程已運行。 因此, 對于進程, 無法重新 (用于示例、 服務、 lsass、 winlogon), 您必須重新啟動測試計算機。
使用以下命令以驗證哪些設置已設置系統級或特定進程: 系統范圍:: 系統范圍:
gflags - r
特定進程:
gflags APP - 名稱 - i
默認情況下, 大堆棧跟蹤深度是 16。 如果要查看深 callstacks, 可以通過運行 GFLAGS 增加此。 單擊以選中
系統注冊表 , 然后鍵入新深度
Max. 堆棧跟蹤捕獲深度 編輯控件中。 單擊
應用 , 并重新啟動計算機。
要點 : 如果正在使用 Windows NT 4.0 Service Pack 6, 您必須使用 Umdh_nt4.exe, 代替 Umdh.exe, 并且您必須使用
gflags - r 命令來設置系統級堆棧跟蹤。 請確保您重新啟動計算機。 WindowsNT 版本 4 上每流程基礎上無效 Umdh_nt4 堆棧跟蹤。 它必須為整個系統設置。
調試符號
最重要步驟以使用 UMDH 之一是以確保您具有好符號文件 (.dbg 或 .pdb 文件) 以獲得良好堆棧跟蹤。 至少, 您需要 Kernel32.dbg 和 Ntdll.dbg 符號文件。 您可以獲得其他調試符號, 您可能需要與您了解多關于哪些組件泄漏內存。 有關如何獲取 Microsoft 組件, 調試符號文件請單擊文章編號以查看 Microsoft 知識庫中相應:
311503 (http://support.microsoft.com/kb/311503/EN-US/) INFO: 使用 Microsoft 符號服務器來獲取調試符號文件
有關如何使用 MicrosoftSymbolServer 以及如何獲取 Windows 符號程序包, 請訪問 Microsoft Web 站點:
當您生成組件與 VisualC++, 值得您沒有將程序數據庫用于編輯和繼續選擇用于 C++ 編譯器選項。 相反, 選擇程序數據庫。 將符號路徑, 初始化到路徑用于 _ NT _ SYMBOL _ PATH 環境變量。 您可以使用 Microsoft 符號服務器來獲取用于 Microsoft 組件符號。
311503 (http://support.microsoft.com/kb/311503/EN-US/) INFO: 使用 Microsoft 符號服務器來獲取調試符號文件
請按照下列步驟來設置 _ NT _ SYMBOL _ PATH 環境變量:
1. | 在控制面板, 雙擊 系統 。 |
2. | 單擊 高級 選項卡, 然后再單擊 環境變量。 |
也可以在命令窗口運行 UMDH 之前設置 _ NT _ SYMBOL _ PATH 環境變量。
注意 : 也包括到 PDB 對組件的應用程序路徑。 例如, _ NT _ SYMBOL _ PATH 路徑設置為以下:
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols;c:\myapplicationssymbols
第第一部分對此路徑指向 MicrosoftSymbolServer 并指出 c:\symbols 文件夾中, 將下載符號使用。 分號后面部分是到 PDB 文件 (符號文件) 專門為泄漏應用程序路徑。
調用 UMDH
只需要命令行參數對于 UMDH 是
- p 選項, 指定將從中獲取堆轉儲進程的 PID。 通過使用任務管理器或 Tlist.exe 程序獲得 PID。 轉日志為類似于以下, 命令將被儲到標準輸出:
umdh - p PID:
向標準錯誤, UMDH 還顯示各種信息性消息并因此如果您不執行重定向其, 與實際日志混合它。 以收集 UMDH 信息性消息文件, 中使用以下命令:
umdh - p PID 2>umdh.msg:
如果要收集日志是由文件, 中 UMDH 轉儲, 使用下列命令之一:
umdh - p PID: umdh.log
- 或 -
umdh f:umdh.log PID - - p:
這些命令是等效。
通過 UMDH 獲得默認日志包含枚舉是堆消費者, 按分配計數排序。 如果還需要所有與其相應堆棧跟蹤, 分配塊的轉儲文件用于調試目的,
- d 選項用于:
umdh - p PID - d:
如果使用此命令, 您可能看到以下 UMDH 日志文件中:
對于跟蹤 BackTrace00046 分配 005F69A0 005F6150:
這些是用于調用該堆棧分配的內存地址。 如果將調試器附加到進程, 您可轉儲內存要查看哪些已分配這些地址上的內容。
如果日志包含太多信息, 就可以僅限于那些具有分配大用戶計數超過特定閾值。 使用以下命令:
umdh - p PID - t: THRESHOLD:
所有命令行選項 (例如, - p、 - f, - t、 - d) 同時指定按任何順序。 下面是更難命令行示例:
umdh - p 123: 1000 - f:umdh.log - d - t:
此命令將轉儲堆對于過程與 PID 123 到 Umdh.log 文件。 它轉儲只堆棧跟蹤, 帳戶超過 1000 分配和它的堆塊通過每個堆棧跟蹤分配地址還轉儲。
另一個有用 UMDH 選項是
- l 選項。 這導致要盡可能調用堆棧中打印文件和行號。
解釋 UMDH 輸出
如果您重定向到文件日志 (PID -:
umdh,) 內容是類似于以下, 從運行 Notepad 進程已獲得它 - p: f:umdh.log UMDH: Logtime 2000-06-28 10:54 - Machine=MYMachine - PID=704
*********** Heap 00270000 Information ********************
Flags: 58000062
Number Of Entries: 87
Number Of Tags: <unknown>
Bytes Allocated: 00008DF0
Bytes Committed: 0000A000
Total FreeSpace: 00001210
Number of Virtual Address chunks used: 1
Address Space Used: <unknown>
Entry Overhead: 8
Creator: (Backtrace00007)
ntdll!RtlDebugCreateHeap+0x00000196
ntdll!RtlCreateHeap+0x0000023F
ntdll!LdrpInitializeProcess+0x00000369
ntdll!LdrpInitialize+0x0000028D
ntdll!KiUserApcDispatcher+0x00000007
*********** Heap 00270000 Hogs ********************
000001A0 bytes in 0x4 allocations (@ 0x00000068) by: BackTrace00031
ntdll!RtlDebugAllocateHeap+0x000000FB
ntdll!RtlAllocateHeapSlowly+0x0000005B
ntdll!RtlAllocateHeap+0x00000D81
ntdll!LdrpAllocateDataTableEntry+0x00000039
ntdll!LdrpMapDll+0x000002A4
ntdll!LdrpLoadImportModule+0x0000010D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpLoadImportModule+0x0000011D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpLoadImportModule+0x0000011D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpInitializeProcess+0x000009DC
ntdll!LdrpInitialize+0x0000028D
ntdll!KiUserApcDispatcher+0x00000007
000001A0 bytes in 0x4 allocations (@ 0x00000068) by: BackTrace00034
ntdll!RtlDebugAllocateHeap+0x000000FB
ntdll!RtlAllocateHeapSlowly+0x0000005B
ntdll!RtlAllocateHeap+0x00000D81
ntdll!LdrpAllocateDataTableEntry+0x00000039
ntdll!LdrpMapDll+0x000002A4
ntdll!LdrpLoadImportModule+0x0000010D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpLoadImportModule+0x0000011D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpLoadImportModule+0x0000011D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpLoadImportModule+0x0000011D
ntdll!LdrpWalkImportDescriptor+0x0000008B
ntdll!LdrpInitializeProcess+0x000009DC
ntdll!LdrpInitialize+0x0000028D
ntdll!KiUserApcDispatcher+0x00000007
日志包含的進程中每個堆轉儲。 在本示例, 日志開頭 270000 地址處堆。 對于堆, 幾全局計數器后日志包含按減少排序順序的大多數分配負責堆棧跟蹤轉儲。 比較不同時間, 上所使用的內存動態時, 可推斷進程中發生什么, 如果任何堆使用它類似于泄漏。 使用 UMDH 時, 您可能會遇到問題
因為未啟用堆棧跟蹤發生常見錯誤使用 UMDH 時。 也, 用于 Ntdll.dll 正確符號使 UMDH 無法運行。 對于其他符號文件, UMDH 運行但日志文件包含堆棧跟蹤沒有函數名稱, 但而具有內部模塊相對地址。 遠程三錯誤指定錯誤 PID。 當您嘗試為沒有啟用堆棧跟蹤過程運行 UMDH 產生以下錯誤信息:
C:\>umdh = MyMachine - PID 1140 UMDH = 1140 連接正在完成模塊枚舉 logtime 06 28 2000 - - - p:: 12:43 - 計算機。 SymGetSymFromName(process, ntdll!RtlpStackTraceDataBase, xxx) 失敗, LastError = 126 ntdll UmdhGetAddrFromName 未能找到堆棧跟蹤 DB 指針) RtlpStackTraceDataBase ! (。 ntdll.dll 符號不正確 ; 我們必須能夠看到非導入符號。
使用以下命令來復查過程, 您正在調查設置:
gflags APPNAME - i
您依賴于系統級堆棧跟蹤時使用以下命令:
gflags - r
這些命令顯示 flags 設置為應用程序的列表。 注意如果是系統級堆棧跟蹤, 功能可能顯示為活動但實際上不激活如果您找不重新啟動計算機運行
gflags -r + ust 命令, 后。 如果要了解具有啟用, 堆棧跟蹤每個應用程序可查看以下注冊表項下 USTEnabled 項:
HKEY NT\CurrentVersion\Image 文件執行選項
如果 UMDH 具有啟用, 堆棧跟蹤進程上運行, 但由于您設置標志, 不重新應用日志中可能會收到以下消息:
沒有用于此分配保存堆棧跟蹤 () 索引 = = 0
如果您運行不要設置正確符號路徑或符號不正確, 和運行 UMDH, 日志中可能會收到錯誤消息。 但是, 只出現錯誤或誤導 callstacks。 若要驗證是否有正確符號, 例如啟動對進程, NTSD 系統調試器:
ntsd 記事本
然后, 從調試器控制臺, 運行
LD 命令以加載符號信息對模塊和
LM 命令以模塊有加載其符號列表。 如果
LM 命令的輸出顯示導出符號加載, 符號是不好。 如果您有加載, PDB 符號符號是好。 如果指定錯誤 PID 可能出現以下錯誤信息:
OpenProcess 失敗, LastError = 0x57
從 VisualBasic 調用 UMDH
最初可能有時用于轉儲隨著時間的日志數量因為泄漏可能不很明顯。 例如, 如果懷疑 Active Server Pages (ASP) Web 應用程序, 是泄漏內存, 它可能有助于出 shells, VisualBasic 中寫入 UMDH COM 組件。 然后可從您的 ASP 頁調用該組件。
下面是一些 VisualBasic 代碼調用 UMDH, 創建一個日志文件是基于當前時間:
Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Public Function GetProcessID()
GetProcessID = GetCurrentProcessId()
End Function
.
.
.
Dim strTime As String
Dim sProcID As String
sProcID = GetProcessID()
strTime = "MYLOG_" & Format(Now(), "hhmm")
Shell ("C:\UMDH\umdh -p:" & sProcID & " -f:d:\logs\" & strTime & ".txt")
使用 Windows NT 4.0 服務軟件包 6a UMDH (SP6a)
Windows NT 4.0 上無效 UMDH 工具隨 DebuggingToolsforWindows 產品一起提供。 自解壓縮可執行 (Umdhnt4tools.exe) 是隨本文并包含以下工具用于與 NT 4.0:
? | Umdh_nt4.exe 和 Dbghelp.dll 這是 UMDH 實用程序的 Windows NT 4.0 SP 6 版本。 |
? | Dhcmp.exe 此工具用于比較兩 UMDH 轉儲以確定其中可能內存泄漏 occurrs。 |
可用于從 Microsoft 下載中心下載下列文件:
August 28, 2002 發布日期:
有關如何下載 Microsoft 支持文件, 請單擊下列文章編號以查看 Microsoft 知識庫中相應:
119591 (http://support.microsoft.com/kb/119591/EN-US/) 如何從聯機服務獲取 Microsoft 支持文件
此文件進行病毒掃描 Microsoft。 Microsoft 使用最新病毒檢測軟件, 投遞文件日期上的可用。 文件存儲在安全增強型服務器有助于防止未經授權更改對該文件。 文件夾, 置于 Umdh_nt4.exe 和 Dbghelp.dll 并再將它們首先在 PATH 環境變量。 使用 Umdh_nt4.exe 代替 UMDH。
是運行 Windows NT 4.0, 計算機上必須使用 Gflags.exe 來設置系統級堆棧跟蹤。 例如:
gflags - r
請確保您重新啟動計算機。 WindowsNT 版本 4.0 上逐個進程無效 Umdh_nt4 堆棧跟蹤。 設置對整個系統。
與 UMDH UMDH_NT4 是, 它不比較日志文件。 例如, 您無法執行以下操作:
UMDH_NT4 dh1.log dh2.log > cmp12.txt
而必須使用 Dhcmp.exe 工具所附帶本文。 類似于以下命令:
DHCMP dh1.log dh2.log > cmp12.txt