• <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>

            PageHeap,調(diào)試Heap問(wèn)題的工具

            《Windows用戶態(tài)程序高效排錯(cuò)》第二章主要介紹用戶態(tài)調(diào)試相關(guān)的知識(shí)和工具。本文主要講了PageHeap,調(diào)試Heap問(wèn)題的工具.

            AD:http://www.cnblogs.com/lidabo/category/542683.html

             

            2.4.2  PageHeap,調(diào)試Heap問(wèn)題的工具

            幸運(yùn)的是,Heap Manager的確提供了主動(dòng)檢查錯(cuò)誤的功能。只需要在注冊(cè)表里面做對(duì)應(yīng)的修改,操作系統(tǒng)就會(huì)根據(jù)設(shè)置來(lái)改變Heap Manager的行為。Pageheap是用來(lái)配置該注冊(cè)表的工具。關(guān)于heap的詳細(xì)信息和原理請(qǐng)參考:

            How to use Pageheap.exe in Windows XP and Windows 2000
            http://support.microsoft.com/kb/286470/en-us

            Pageheap,Gflag和后面介紹的Application Verifier工具一樣,都是方便修改對(duì)應(yīng)注冊(cè)表的工具。如果不使用這兩個(gè)工具,直接修改注冊(cè)表也可以達(dá)到一樣的效果。3個(gè)工具里面Application Verifier是目前的主流,Gflag是老牌。除了heap問(wèn)題外,這兩個(gè)工具還可以修改其他的調(diào)試選項(xiàng),后面都有說(shuō)明。Pageheap.exe工具主要針對(duì)heap問(wèn)題,使用起來(lái)簡(jiǎn)單方便。目前gflag.exe包含在調(diào)試器的安裝包中,Application Verifier可以單獨(dú)下載安裝。如果調(diào)試安裝包中沒(méi)有包含pageheap.exe,可以從這里下載:

            http://www.heijoy.com/debugdoc/pageheap.zip
            http://blogs.msdn.com/lixiong/attachment/2792912.ashx

            簡(jiǎn)單例子的多種情況

            看幾個(gè)簡(jiǎn)單的但是卻很有意義的例子:

            用release模式編譯運(yùn)行下面的代碼:

             char *p=(char*)malloc(1024);
            p[1024]=1;

            這里往分配的空間多寫(xiě)一個(gè)字節(jié)。但是在release模式下運(yùn)行,程序不會(huì)崩潰。

            假設(shè)上面的代碼編譯成mytest.exe,用下面的方法可以對(duì)mytest.exe激活pageheap:

            C:\Debuggers\pageheap>pageheap /enable mytest.exe /full    

            直接運(yùn)行pageheap可以查看當(dāng)前pageheap的激活狀態(tài):

            C:\Debuggers\pageheap>pageheap
            mytest.exe: page heap enabled with flags (full traces )

            當(dāng)激活pageheap后,重新運(yùn)行一次上面的代碼,程序就崩潰了。

            (直接雙擊運(yùn)行程序和在Windbg中用調(diào)試模式運(yùn)行程序,觀察到的崩潰有差別。在Windbg中運(yùn)行,pageheap會(huì)首先觸發(fā)break point異常,同時(shí)pageheap還會(huì)在調(diào)試器中輸出額外的調(diào)試信息方便調(diào)試。)

            上面的例子說(shuō)明了pageheap能夠讓錯(cuò)誤盡快暴露出來(lái)。接下來(lái)我們稍微修改一下代碼:

             char *p=(char*)malloc(1023);
            p[1023]=1;

            試試看,修改后的代碼還會(huì)導(dǎo)致程序崩潰嗎?

            根據(jù)我的測(cè)試,分配1023字節(jié)的情況下,哪怕激活pageheap,也不會(huì)崩潰。你能說(shuō)明原因嗎?如果看不出來(lái),可以檢查一下每次malloc返回的地址的數(shù)值,注意對(duì)這個(gè)數(shù)值在二進(jìn)制上敏感一點(diǎn),然后結(jié)合Heap Manager和pageheap的原理思考一下,看看有沒(méi)有發(fā)現(xiàn)。

            對(duì)于上面兩種代碼,如果用debug模式編譯,激活pageheap,程序會(huì)崩潰嗎?根據(jù)我的測(cè)試,無(wú)論是否激活pageheap,debug模式都不會(huì)崩潰的。你能想到原因嗎?

            再來(lái)看下面一段代碼:

             char *p=(char*)malloc(1023);
            free(p);
            free(p);

            這里顯然有double free的問(wèn)題。

            如果沒(méi)有激活pageheap,分別在debug和release模式下運(yùn)行,根據(jù)我的測(cè)試,debug模式下會(huì)崩潰,release模式下運(yùn)行正常。

            如果激活pageheap,同樣在debug/release模式下運(yùn)行。根據(jù)我的測(cè)試,在兩種模式下都會(huì)崩潰。如果細(xì)心觀察,會(huì)發(fā)現(xiàn)兩種模式下,崩潰后彈出的提示各自不同。你能想到原因嗎?

            如果有興趣,你還可以測(cè)試一下heap誤用的其他幾種情況,看看pageheap是不是都有幫助。

            Heap上的內(nèi)存泄漏和內(nèi)存碎片

            從上面的例子,可以很清楚地看到pageheap對(duì)于檢查這類(lèi)問(wèn)題的幫助。同時(shí)也可以看到,pageheap無(wú)法保證檢查出所有潛在問(wèn)題,比如分配1023個(gè)字節(jié),但是寫(xiě)1024個(gè)字節(jié)這種情況。只有理解pageheap的工作原理,同時(shí)對(duì)問(wèn)題作認(rèn)真的思考和測(cè)試后,才會(huì)理解其中的差別。

            除了Heap使用不當(dāng)導(dǎo)致崩潰外,還有一類(lèi)問(wèn)題是內(nèi)存泄漏。內(nèi)存泄漏是指隨著程序的運(yùn)行,內(nèi)存消耗越來(lái)越多,最后發(fā)生內(nèi)存不足,或者整體性能下降。從代碼上看,這類(lèi)問(wèn)題是由于內(nèi)存使用后沒(méi)有及時(shí)釋放導(dǎo)致的。這里的內(nèi)存,可以是VirtualAlloc分配的,也有可能是HeapAllocate分配的。

            這里只討論Heap相關(guān)的內(nèi)存泄漏。檢查內(nèi)存泄漏是一個(gè)比較大的題目,第4章會(huì)作詳細(xì)討論。

            舉個(gè)例子,客戶開(kāi)發(fā)一個(gè)cd刻錄程序。每次把盤(pán)片中所有內(nèi)容寫(xiě)入內(nèi)存,然后開(kāi)始刻錄。如果每次刻錄完成后都忘記去釋放分配的空間,那么最多能夠刻3張CD。因?yàn)?張CD,每一張600MB,加在一起就是1.8GB,瀕臨2GB的上限。

            另外還有一種跟內(nèi)存泄漏相關(guān)的問(wèn)題,是內(nèi)存碎片(Fragmentation)。內(nèi)存碎片是指內(nèi)存被分割成很多的小塊,以至于很難找到連續(xù)的內(nèi)存來(lái)滿足比較大的內(nèi)存申請(qǐng)。導(dǎo)致內(nèi)存碎片常見(jiàn)原因有兩種,一種是加載了過(guò)多DLL,還有一種是小塊Heap的頻繁使用。

            DLL分割內(nèi)存空間最常見(jiàn)的情況是ASP.NET中的batch compilation沒(méi)有打開(kāi),導(dǎo)致每一個(gè)ASP.NET頁(yè)面都會(huì)被編譯成一個(gè)單獨(dú)的DLL文件。運(yùn)行一段時(shí)間后,就可以看到幾千個(gè)DLL文件加載到進(jìn)程中。一個(gè)極端的例子是5000個(gè)DLL把2GB內(nèi)存平均分成5000份,導(dǎo)致每一份的大小在400KB左右(假設(shè)DLL本身只占用1個(gè)字節(jié)),于是無(wú)法申請(qǐng)大于400KB的內(nèi)存,哪怕總的內(nèi)存還是接近2GB。對(duì)于這種情況的檢查很簡(jiǎn)單,列一下當(dāng)前進(jìn)程中所有加載起來(lái)的DLL就可以看出問(wèn)題來(lái)。

            對(duì)于小塊Heap的頻繁使用導(dǎo)致的內(nèi)存分片,可以參考下面的解釋?zhuān)?pre>Heap fragmentation is often caused by one of the following two reasons
            1. Small heap memory blocks that are leaked (allocated but never freed) over time
            2. Mixing long lived small allocations with short lived long allocations
            Both of these reasons can prevent the NT heap manager from using free
            memory efficiently since they are spread as small fragments that cannot
            be used as a single large allocation

            為了更好地理解上面的解釋?zhuān)紤]這樣的情況。假設(shè)開(kāi)發(fā)人員設(shè)計(jì)了一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)描述一首歌曲,數(shù)據(jù)結(jié)構(gòu)分成兩部分,第一部分是歌曲的名字、作者和其他相關(guān)的描述性信息,第二部分是歌曲的二進(jìn)制內(nèi)容。顯然第一部分比第二部分小得多。假設(shè)第一部分長(zhǎng)度1KB,第二部分399KB。每處理一首歌需要調(diào)用兩次內(nèi)存分配函數(shù),分別分配數(shù)據(jù)結(jié)構(gòu)第一部分和第二部分需要的空間。

            假設(shè)每次處理完成后,只釋放了數(shù)據(jù)結(jié)構(gòu)的第二部分,忘記釋放第一部分,這樣每處理一次,就會(huì)留下1個(gè)1KB的數(shù)據(jù)塊沒(méi)有釋放。程序長(zhǎng)時(shí)間運(yùn)行后,留下的1KB數(shù)據(jù)塊就會(huì)很多,雖然HeapManager的薄計(jì)信息中可能記錄了有很多399KB的數(shù)據(jù)塊可以分配,但是如果要申請(qǐng)500KB的內(nèi)存,就會(huì)因?yàn)檎也坏竭B續(xù)的內(nèi)存塊而失敗。對(duì)于內(nèi)存碎片的調(diào)試,可以參考最后的案例討論。在Windows 2000上,可以用下面的方法來(lái)緩解問(wèn)題:

            The Windows XP Low Fragmentation Heap Algorithm 
            Feature Is Available for Windows 2000
            http://support.microsoft.com/?id=816542

            關(guān)于 CLR上內(nèi)存碎片的討論和圖文詳解,請(qǐng)參考:

             .NET Memory usage - A restaurant analogy
            http://blogs.msdn.com/tess/archive/2006/09/06/742568.aspx

            posted on 2017-02-03 16:35 FongLuo 閱讀(468) 評(píng)論(0)  編輯 收藏 引用


            只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
            網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


            <2016年11月>
            303112345
            6789101112
            13141516171819
            20212223242526
            27282930123
            45678910

            導(dǎo)航

            常用鏈接

            留言簿

            隨筆分類(lèi)(11)

            隨筆檔案(79)

            文章檔案(1)

            收藏夾(38)

            學(xué)習(xí)網(wǎng)站

            一般網(wǎng)站

            最新隨筆

            搜索

            積分與排名

            最新評(píng)論

            閱讀排行榜

            一本久久a久久精品vr综合| 久久精品国产99国产精品导航 | 青草影院天堂男人久久| 久久久久久精品无码人妻| 人妻中文久久久久| 久久久久久久国产免费看| 色综合合久久天天综合绕视看| 丁香狠狠色婷婷久久综合| 亚洲AV无码一区东京热久久| 久久精品中文字幕一区| 2021国内精品久久久久久影院| 一97日本道伊人久久综合影院| 国产精品丝袜久久久久久不卡| 国产精品99久久久久久猫咪| 草草久久久无码国产专区| 精品一久久香蕉国产线看播放| 久久国产香蕉一区精品| 国产精品内射久久久久欢欢| 久久99精品久久久久久野外 | 久久婷婷人人澡人人| 国产精品久久久天天影视香蕉 | 久久影视综合亚洲| 中文国产成人精品久久亚洲精品AⅤ无码精品 | 精品一久久香蕉国产线看播放 | 久久久91人妻无码精品蜜桃HD| 久久精品国产色蜜蜜麻豆| 久久最新免费视频| 国产激情久久久久久熟女老人| 看久久久久久a级毛片| 丰满少妇人妻久久久久久| 99久久夜色精品国产网站| 久久男人中文字幕资源站| 伊人久久大香线蕉亚洲五月天| 99国产精品久久久久久久成人热| 久久91精品久久91综合| 亚洲精品成人久久久| 久久久久无码精品国产| 久久久久18| 久久精品国产亚洲AV电影| 久久精品国产99久久丝袜| 久久久无码一区二区三区|