• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            S.l.e!ep.¢%

            像打了激速一樣,以四倍的速度運(yùn)轉(zhuǎn),開心的工作
            簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
            posts - 1098, comments - 335, trackbacks - 0, articles - 1
              C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

            如何用WinDbg定位內(nèi)存泄露?

            Posted on 2009-03-27 21:38 S.l.e!ep.¢% 閱讀(6795) 評論(1)  編輯 收藏 引用 所屬分類: WinDbg
            如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-04, 10:35 上午 Reply Quote
            我用最近用VC在做一個應(yīng)用程序,其中使用到了一些其他人員開發(fā)的DLL,當(dāng)我在VC中運(yùn)行該程序并退出時,輸出窗口中顯示很多Object Dump,雙擊這些信息也不能定位到我的源碼當(dāng)中,我懷疑這些內(nèi)存泄漏來自于我調(diào)用的DLL中,所以我向請教一下如何通過WinDbg來定位內(nèi)存泄漏是發(fā)生在我的程序中還是DLL中?謝謝!
            IP 地址: 已記錄?? 報告
            Raymond 離線,最后訪問時間: 2009-3-11 12:55:32 Raymond

            無等級
            注冊: 2005-12-19
            發(fā) 貼: 298
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-04, 12:42 下午 Reply Quote
            1)你能把你看到的轉(zhuǎn)儲信息(Dump)復(fù)制一些過來么?
            2)如果你有《軟件調(diào)試》這本書,那么請閱讀一下第23章,特別是以下幾個小節(jié):
            23.7.2 DH和UMDH工具 668
            23.7.3 定位內(nèi)存泄漏 668
            23.14 堆塊轉(zhuǎn)儲 700
            23.15 泄漏轉(zhuǎn)儲 704
            23.15.1 _CrtDumpMemoryLeaks 704
            23.15.2 何時調(diào)用 705
            23.15.3 定位導(dǎo)致泄漏的源代碼 706
            IP 地址: 已記錄?? 報告
            zxh65 離線,最后訪問時間: 2008-8-7 23:03:54 zxh65

            無等級
            注冊: 2008-08-03
            發(fā) 貼: 4
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-04, 13:05 下午 Reply Quote
            謝謝Raymond!
            因為轉(zhuǎn)儲信息比較多,我這里就貼一小部分!
            {152} normal block at 0x01078320, 12 bytes long.
            Data: 08 79 65 00 48 82 07 01 00 00 00 00
            {151} normal block at 0x010782C0, 36 bytes long.
            Data: CD CD CD CD CD CD CD CD 00 00 00 00 00 00 00 00
            {150} normal block at 0x01078248, 56 bytes long.
            Data: F4 77 65 00 00 00 00 00 68 71 07 01 90 3A 09 10
            {149} normal block at 0x01077208, 4096 bytes long.
            Data: 48 82 07 01 68 83 07 01 88 84 07 01 A8 85 07 01
            {148} normal block at 0x010771C8, 4 bytes long.
            Data: CD CD CD CD
            {147} normal block at 0x01077168, 32 bytes long.
            Data: 40 79 65 00 01 00 00 00 00 00 00 00 00 00 00 00
            {146} normal block at 0x010770D0, 92 bytes long.
            Data: 4C 76 65 00 D8 55 15 00 FF FF FF FF 00 00 00 00
            {145} normal block at 0x01073B10, 8 bytes long.
            Data: 10 3B 07 01 CD CD CD CD
            {144} normal block at 0x01077070, 32 bytes long.
            Data: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
            {143} normal block at 0x01077018, 28 bytes long.
            Data: 50 54 15 00 FF FF FF FF 00 00 00 00 00 00 00 00
            {142} normal block at 0x01073A90, 64 bytes long.
            Data: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
            {141} normal block at 0x010739A0, 180 bytes long.
            Data: C4 0B 13 10 90 3A 07 01 00 00 00 00 A4 79 1A 10
            {138} normal block at 0x010737D8, 6 bytes long.
            Data: 00 00 00 00 00 00
            {137} normal block at 0x01073790, 8 bytes long.
            Data: <H7> 48 37 07 01 CD CD CD CD
            {136} normal block at 0x01073748, 8 bytes long.
            Data: 90 37 07 01 18 5E 1A 10
            {135} normal block at 0x010736E8, 32 bytes long.
            Data: 20 79 12 10 A8 53 15 00 FF FF FF FF 00 00 00 00
            {134} normal block at 0x010736A0, 12 bytes long.
            Data: 90 37 07 01 01 00 00 00 A4 79 1A 10
            最近正在看你的《軟件調(diào)試》,只是我才看到第四章,晚上回去我先看看23章!
            另外,謝謝你寫《軟件調(diào)試》這本書,難得看到國人寫出這么好的書,我一定好好把書讀透,如果有什么疑問還要向你請教!
            IP 地址: 已記錄?? 報告
            Raymond 離線,最后訪問時間: 2009-3-11 12:55:32 Raymond

            無等級
            注冊: 2005-12-19
            發(fā) 貼: 298
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-04, 21:09 下午 Reply Quote
            《軟件調(diào)試》的702頁介紹了堆塊轉(zhuǎn)儲的細(xì)節(jié),取其中的一個堆塊為例:
            {137} normal block at 0x01073790, 8 bytes long.
            Data: <H7> 48 37 07 01 CD CD CD CD
            137是堆塊的分配序號,堆塊的類型為普通堆塊,位置為0x01073790,用戶區(qū)長度為8字節(jié)。
            Data后為用戶數(shù)據(jù)區(qū)的前16字節(jié),因為這個數(shù)據(jù)區(qū)只有8字節(jié),所以即所有8字節(jié)。<H7>是這8字節(jié)的ASCII碼顯示(其它6字節(jié)為不可顯示的ASCII碼)。其中的CD CD CD CD 是CRT在分配堆塊時自動填充的固定內(nèi)容(《軟件調(diào)試》P696)。這說明這8個字節(jié)的堆塊,應(yīng)用程序使用過前4個字節(jié),后四個字節(jié)沒有使用過。

            對于這樣的內(nèi)存泄漏,有很多種辦法,你首先可以試一下23.13.1節(jié)介紹的內(nèi)存分配序號斷點,也就是重新運(yùn)行程序,在盡可能早的時候(比如入口),設(shè)置序號斷點(將_crtBreakAlloc變量設(shè)置為要中斷的序號,比如137),讓CRT分配到指定的內(nèi)存塊時中斷。中斷下來后,可以根據(jù)棧回溯判斷是哪個模塊在分配內(nèi)存,記錄后,再退出程序,如果這個堆塊仍出現(xiàn)在轉(zhuǎn)儲列表中,那么剛才那個模塊便值得懷疑了。

            如果你有被懷疑的模塊源代碼,那么可以使用23.15.3節(jié)介紹的方法讓堆塊轉(zhuǎn)儲信息中包含源程序的文件名和行號,即下面的樣子:
            C:\dig\dbg\author\code\chap23\MemLeak\MemLeak.cpp(22) : {74} normal block at 0x00371000, 20 bytes long.
            Data: CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD




            IP 地址: 已記錄?? 報告
            zxh65 離線,最后訪問時間: 2008-8-7 23:03:54 zxh65

            無等級
            注冊: 2008-08-03
            發(fā) 貼: 4
            設(shè)置序號斷點還不能定位
            ?2008-08-05, 10:15 上午 Reply Quote
            Raymond:感謝你的回復(fù),我翻閱了23.13.1節(jié),在程序入口處設(shè)置了序號斷點,但我的程序并沒有在序號斷點處中斷,我的判斷如下,不知道是否正確,還望指正!
            我程序是使用lib文件隱式鏈接DLL的,當(dāng)我在VC中按F11到程序入口的時候各DLL已經(jīng)載入完成,如果序號所對應(yīng)內(nèi)存的分配的確是在某DLL的DllMain中的話此時再設(shè)置序號斷點已經(jīng)晚了,所以最終序號斷點沒有中斷。不知道我這樣的分析是否正確?如果正確我該如何將序號斷點的設(shè)置再進(jìn)一步提前到在DLL加載之前呢?
            IP 地址: 已記錄?? 報告
            neilhsu 離線,最后訪問時間: 2009-3-10 18:23:13 手語

            無等級
            注冊: 2008-06-06
            發(fā) 貼: 60
            Wink [;)] Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-05, 10:25 上午 Reply Quote

            一般我用兩種方法:

            1. 用Debug Diagnostic Tool的Leak監(jiān)測分析功能,注意配置好PDB文件。

            ???DebugDiag 會生成完整的Leak Report。看看幫助很方便。

            2. 用WinDBG的!heap擴(kuò)展命令。注意要為你的程序打開Normal PageHeap。

            ???然后當(dāng)內(nèi)存出現(xiàn)明顯泄漏時用 !heap -l 命令分析內(nèi)存。-l 參數(shù)使用類似Java/C#的Garbage Collection算法,這樣能找到大部分在程序中沒有被引用的HeapBlock。

            ???這是一個示例輸出:

            0:011> !heap -l
            Searching the memory for potential unreachable busy blocks.
            ......
            Heap 017a0000
            Scanning VM ...
            Scanning references from 3586 busy blocks (0 MBytes) ...
            Entry???????????User?????????Heap??????????? Segment????????Size? PrevSize? Unused??? Flags
            -----------------------------------------------------------------------------
            00253198? 002531a0? 00250000? 00250000??????? b8??????? 78??????? 14? busy extra
            00253250? 00253258? 00250000? 00250000??????? 78??????? b8??????? 13? busy extra
            00286a38? 00286a40? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra
            00286af0? 00286af8? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra
            00286ba8? 00286bb0? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra
            00286c60? 00286c68? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra
            00286d18? 00286d20? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra
            00286dd0? 00286dd8? 00250000? 00250000??????? b8??????? b8??????? 15? busy extra

            ???找到最常出現(xiàn)的Size值(這里是b8),一般就是持續(xù)泄漏的內(nèi)存塊大小。隨便選一行,記下Entry地址(比如00286a3)。

            ???dt _DPH_BLOCK_INFORMATION 00286a3 + 8???//8 是HeapEntry結(jié)構(gòu)的大小,跟在其后的就是PageHeap meta data,結(jié)構(gòu)名是_DPH_BLOCK_INFORMATION.

            ???0:011> dt _DPH_BLOCK_INFORMATION 00286a3 + 8
            ntdll!_DPH_BLOCK_INFORMATION
            ?? +0x000 StartStamp?????? : 0xabcdaaaa
            ?? +0x004 Heap???????????? : 0x80151000
            ?? +0x008 RequestedSize??? : 0x7b
            ?? +0x00c ActualSize?????? : 0xa3
            ?? +0x010 FreeQueue??????? : _LIST_ENTRY [ 0x2e - 0x0 ]
            ?? +0x010 TraceIndex?????? : 0x2e
            ?? +0x018 StackTrace?????? : 0x00357140
            ?? +0x01c EndStamp???????? : 0xdcbaaaaa

            ???看到StackTrace那行,這是相應(yīng)的user mode stack trace database的地址。

            0:011> dds 0x00357140
            00357140? abcdaaaa
            ......
            00357160? 7c949d18 ntdll!RtlAllocateHeapSlowly+0x44
            00357164? 7c91b298 ntdll!RtlAllocateHeap+0xe64
            00357168? 004017fe 06_DebugDiag_MemoryLeak!MyHeapAlloc+0x1e [g:\debugging101\projects\06_debugdiag_memoryleak\06_debugdiag_memoryleak\06_debugdiag_memoryleak.cpp @ 11]
            0035716c? 0040182b 06_DebugDiag_MemoryLeak!WorkerThread+0x1b [g:\debugging101\projects\06_debugdiag_memoryleak\06_debugdiag_memoryleak\06_debugdiag_memoryleak.cpp @ 27]
            00357170? 7c80b683 kernel32!BaseThreadStart+0x37

            ???這就是上次通過Heap Manager函數(shù)操作這個HeapBlock的StackTrace,一般也就是分配這個Block的地方。

            ???希望可以幫到你。


            鴻鵠安知燕雀之志
            IP 地址: 已記錄?? 報告
            Raymond 離線,最后訪問時間: 2009-3-11 12:55:32 Raymond

            無等級
            注冊: 2005-12-19
            發(fā) 貼: 298
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-05, 12:48 下午 Reply Quote
            1)如果你覺得main/winmain入口還不夠早,那么可以使用WinDBG,在進(jìn)程的初始斷點命中后,啟用模塊加載事件(debug > event filters > load module),然后在每個CRT DLL加載后設(shè)置序號斷點。
            2)被調(diào)試進(jìn)程中可能有幾個CRT實例,應(yīng)該修改所有實例的_crtBreakAlloc變量,才能保證不會遺漏。以myapp.exe為例,myapp內(nèi)可能有一份靜態(tài)鏈接進(jìn)來的CRT,即myapp!_crtBreakAlloc。而MSVCRT60.DLL這樣的模塊中也有CRT實例。

            手語說的在Win32堆這一層次來分析也是可行的,而且把握更大,但是就要求你先要熟悉一下Win32堆的常識,《軟件調(diào)試》23章的前10節(jié)做了詳細(xì)的介紹。
            IP 地址: 已記錄?? 報告
            zxh65 離線,最后訪問時間: 2008-8-7 23:03:54 zxh65

            無等級
            注冊: 2008-08-03
            發(fā) 貼: 4
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-07, 10:15 上午 Reply Quote
            To Raymond:
            你的回復(fù)中我有兩點疑問,特再次請教!
            1、在WinDbg中啟用模塊加載事件有兩個選項,一個是Execution,另一個是Continue。我試了一下,將Execution選項設(shè)為Enable時,重新在WinDbg我的程序在其加載每個DLL時都會中斷;而Continue選項無論設(shè)置哪個值都沒有明顯影響。我看了一下幫助,說這兩個選項分別用來改變中斷狀態(tài)(break status)和處理狀態(tài)(handling status),我不知道上述兩個狀態(tài)尤其是第二個狀態(tài)的作用是什么?
            2、在WinDbg中如何設(shè)置序號斷點?
            To 手語:
            你提供的兩個方法我都還沒用過,我最近正在按照Raymond的提示在看《軟件調(diào)試》的相關(guān)章節(jié),感謝你的幫助!
            IP 地址: 已記錄?? 報告
            Raymond 離線,最后訪問時間: 2009-3-11 12:55:32 Raymond

            無等級
            注冊: 2005-12-19
            發(fā) 貼: 298
            Re: 如何用WinDbg定位內(nèi)存泄露?
            ?2008-08-07, 12:50 下午 Reply Quote
            ZXH,
            Continue選項只對異常類事件有意義(參見《軟件調(diào)試》30.9.3節(jié),P48)。
            WinDBG中可以直接使用ed命令來編輯_crtBreakAlloc變量(《軟件調(diào)試》P698),例如你要編輯靜態(tài)鏈接到myapp.exe中的CRT實例,那么便執(zhí)行:ed myapp!__crtBreakAlloc 。

            Feedback

            # re: 如何用WinDbg定位內(nèi)存泄露?   回復(fù)  更多評論   

            2011-08-24 11:11 by sghcpt
            To S.l.e!ep.¢%
            我在網(wǎng)上看到你的提問關(guān)于“如何用WinDbg定位內(nèi)存泄露? ”,我也遇到這樣的情況,我的程序運(yùn)行一段時間會出現(xiàn)錯誤,但不知道是我的代碼有問題還是別人的dll庫有問,想請問你一下,你上面的問題處理好了嗎?是怎樣處理的?
            嫩草影院久久国产精品| 久久精品中文字幕无码绿巨人| 久久精品国产秦先生| 国产综合免费精品久久久| 久久综合色老色| 中文字幕久久欲求不满| 思思久久99热只有频精品66| 精品久久久久久久久中文字幕| 模特私拍国产精品久久| 久久精品国产福利国产琪琪| 色婷婷久久综合中文久久蜜桃av| 国产 亚洲 欧美 另类 久久| 人妻无码久久一区二区三区免费| 久久久久久久久久久免费精品| 久久天天躁狠狠躁夜夜躁2O2O| 亚洲国产高清精品线久久| 亚洲国产精品人久久| 97久久超碰国产精品旧版| 日韩人妻无码一区二区三区久久99| 人人狠狠综合久久亚洲婷婷 | 久久久久无码精品国产| 亚洲欧美日韩精品久久亚洲区| 久久久国产精品福利免费| 无码国产69精品久久久久网站| 一本久久精品一区二区| 热RE99久久精品国产66热| 久久久久无码中| 久久精品成人免费观看97| 狠狠色综合久久久久尤物| 久久精品国产亚洲精品| 久久久WWW成人| 蜜臀久久99精品久久久久久| 久久国产精品免费一区二区三区| 香港aa三级久久三级| 国产午夜精品理论片久久| 久久久久国产一区二区| 亚洲精品成人网久久久久久| 久久国产精品无| 无码人妻久久一区二区三区 | 久久精品无码一区二区三区日韩 | 欧美亚洲日本久久精品|