青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

<2006年10月>
24252627282930
1234567
891011121314
15161718192021
22232425262728
2930311234

統計

  • 隨筆 - 44
  • 文章 - 0
  • 評論 - 86
  • 引用 - 0

常用鏈接

留言簿(6)

隨筆分類(31)

隨筆檔案(44)

Mining

最新隨筆

搜索

  •  

最新評論

閱讀排行榜

評論排行榜

用BoundsChecker檢測內存泄漏 (zz)
  BoundsChecker采用一種被稱為 Code Injection的技術,來截獲對分配內存和釋放內存的函數的調用。簡單地說,當你的程序開始運行時,BoundsChecker的DLL被自動載入進程的地址空間(這可以通過system-level的Hook實現),然后它會修改進程中對內存分配和釋放的函數調用,讓這些調用首先轉入它的代碼,然后再執行原來的代碼。BoundsChecker在做這些動作的時,無須修改被調試程序的源代碼或工程配置文件,這使得使用它非常的簡便、直接。

  這里我們以malloc函數為例,截獲其他的函數方法與此類似。

  需要被截獲的函數可能在DLL中,也可能在程序的代碼里。比如,如果靜態連結C-Runtime Library,那么malloc函數的代碼會被連結到程序里。為了截獲住對這類函數的調用,BoundsChecker會動態修改這些函數的指令。

  以下兩段匯編代碼,一段沒有BoundsChecker介入,另一段則有BoundsChecker的介入:
126:?_CRTIMP?void?*?__cdecl?malloc?(
127:?size_t?nSize
128:?)
129:?{

00403C10?push?ebp
00403C11?mov?ebp,esp
130:?return?_nh_malloc_dbg(nSize,?_newmode,?_NORMAL_BLOCK,?NULL,?0);
00403C13?push?
0
00403C15?push?
0
00403C17?push?
1
00403C19?mov?eax,[__newmode?(0042376c)]
00403C1E?push?eax
00403C1F?mov?ecx,dword?ptr?[nSize]
00403C22?push?ecx
00403C23?call?_nh_malloc_dbg?(00403c80)
00403C28?add?esp,14h
131:?}
以下這一段代碼有BoundsChecker介入:
126:?_CRTIMP?void?*?__cdecl?malloc?(
127:?size_t?nSize
128:?)
129:?{

00403C10?jmp?01F41EC8
00403C15?push?
0
00403C17?push?
1
00403C19?mov?eax,[__newmode?(0042376c)]
00403C1E?push?eax
00403C1F?mov?ecx,dword?ptr?[nSize]
00403C22?push?ecx
00403C23?call?_nh_malloc_dbg?(00403c80)
00403C28?add?esp,14h
131:?}

  當BoundsChecker介入后,函數malloc的前三條匯編指令被替換成一條jmp指令,原來的三條指令被搬到地址01F41EC8處了。當程序進入malloc后先jmp到01F41EC8,執行原來的三條指令,然后就是BoundsChecker的天下了。大致上它會先記錄函數的返回地址(函數的返回地址在stack上,所以很容易修改),然后把返回地址指向屬于BoundsChecker的代碼,接著跳到malloc函數原來的指令,也就是在00403c15的地方。當malloc函數結束的時候,由于返回地址被修改,它會返回到BoundsChecker的代碼中,此時BoundsChecker會記錄由malloc分配的內存的指針,然后再跳轉到到原來的返回地址去。

  如果內存分配/釋放函數在DLL中,BoundsChecker則采用另一種方法來截獲對這些函數的調用。BoundsChecker通過修改程序的DLL Import Table讓table中的函數地址指向自己的地址,以達到截獲的目的。

  截獲住這些分配和釋放函數,BoundsChecker就能記錄被分配的內存或資源的生命周期。接下來的問題是如何與源代碼相關,也就是說當BoundsChecker檢測到內存泄漏,它如何報告這塊內存塊是哪段代碼分配的。答案是調試信息(Debug Information)。當我們編譯一個Debug版的程序時,編譯器會把源代碼和二進制代碼之間的對應關系記錄下來,放到一個單獨的文件里(.pdb)或者直接連結進目標程序,通過直接讀取調試信息就能得到分配某塊內存的源代碼在哪個文件,哪一行上。使用Code Injection和Debug Information,使BoundsChecker不但能記錄呼叫分配函數的源代碼的位置,而且還能記錄分配時的Call Stack,以及Call Stack上的函數的源代碼位置。這在使用像MFC這樣的類庫時非常有用,以下我用一個例子來說明:

void?ShowXItemMenu()
{
 …
 CMenu?menu;

 menu.CreatePopupMenu();
 
//add?menu?items.
 menu.TrackPropupMenu();
 …
}

void?ShowYItemMenu(?)
{
 …
 CMenu?menu;
 menu.CreatePopupMenu();
 
//add?menu?items.
 menu.TrackPropupMenu();
 menu.Detach();
//this?will?cause?HMENU?leak
 …
}

BOOL?CMenu::CreatePopupMenu()
{
 …
 hMenu?
=?CreatePopupMenu();
 …
}
當調用ShowYItemMenu()時,我們故意造成HMENU的泄漏。但是,對于BoundsChecker來說被泄漏的HMENU是在class CMenu::CreatePopupMenu()中分配的。假設的你的程序有許多地方使用了CMenu的CreatePopupMenu()函數,如CMenu::CreatePopupMenu()造成的,你依然無法確認問題的根結到底在哪里,在ShowXItemMenu()中還是在ShowYItemMenu()中,或者還有其它的地方也使用了CreatePopupMenu()?有了Call Stack的信息,問題就容易了。BoundsChecker會如下報告泄漏的HMENU的信息:
Function
File
Line

CMenu::CreatePopupMenu
E:\
8168\vc98\mfc\mfc\include\afxwin1.inl
1009

ShowYItemMenu
E:\testmemleak\mytest.cpp
100
  
這里省略了其他的函數調用

如此,我們很容易找到發生問題的函數是ShowYItemMenu()。當使用MFC之類的類庫編程時,大部分的API調用都被封裝在類庫的class里,有了Call Stack信息,我們就可以非常容易的追蹤到真正發生泄漏的代碼。

  記錄Call Stack信息會使程序的運行變得非常慢,因此默認情況下BoundsChecker不會記錄Call Stack信息??梢园凑找韵碌牟襟E打開記錄Call Stack信息的選項開關:

  1. 打開菜單:BoundsChecker|Setting…

  2. 在Error Detection頁中,在Error Detection Scheme的List中選擇Custom

  3. 在Category的Combox中選擇 Pointer and leak error check

  4. 鉤上Report Call Stack復選框

  5. 點擊Ok

  基于Code Injection,BoundsChecker還提供了API Parameter的校驗功能,memory over run等功能。這些功能對于程序的開發都非常有益。由于這些內容不屬于本文的主題,所以不在此詳述了。

  盡管BoundsChecker的功能如此強大,但是面對隱式內存泄漏仍然顯得蒼白無力。所以接下來我們看看如何用Performance Monitor檢測內存泄漏。

  使用Performance Monitor檢測內存泄漏

  NT的內核在設計過程中已經加入了系統監視功能,比如CPU的使用率,內存的使用情況,I/O操作的頻繁度等都作為一個個Counter,應用程序可以通過讀取這些Counter了解整個系統的或者某個進程的運行狀況。Performance Monitor就是這樣一個應用程序。

  為了檢測內存泄漏,我們一般可以監視Process對象的Handle Count,Virutal Bytes 和Working Set三個Counter。Handle Count記錄了進程當前打開的HANDLE的個數,監視這個Counter有助于我們發現程序是否有Handle泄漏;Virtual Bytes記錄了該進程當前在虛地址空間上使用的虛擬內存的大小,NT的內存分配采用了兩步走的方法,首先,在虛地址空間上保留一段空間,這時操作系統并沒有分配物理內存,只是保留了一段地址。然后,再提交這段空間,這時操作系統才會分配物理內存。所以,Virtual Bytes一般總大于程序的Working Set。監視Virutal Bytes可以幫助我們發現一些系統底層的問題; Working Set記錄了操作系統為進程已提交的內存的總量,這個值和程序申請的內存總量存在密切的關系,如果程序存在內存的泄漏這個值會持續增加,但是Virtual Bytes卻是跳躍式增加的。

  監視這些Counter可以讓我們了解進程使用內存的情況,如果發生了泄漏,即使是隱式內存泄漏,這些Counter的值也會持續增加。但是,我們知道有問題卻不知道哪里有問題,所以一般使用Performance Monitor來驗證是否有內存泄漏,而使用BoundsChecker來找到和解決。

  當Performance Monitor顯示有內存泄漏,而BoundsChecker卻無法檢測到,這時有兩種可能:第一種,發生了偶發性內存泄漏。這時你要確保使用Performance Monitor和使用BoundsChecker時,程序的運行環境和操作方法是一致的。第二種,發生了隱式的內存泄漏。這時你要重新審查程序的設計,然后仔細研究Performance Monitor記錄的Counter的值的變化圖,分析其中的變化和程序運行邏輯的關系,找到一些可能的原因。這是一個痛苦的過程,充滿了假設、猜想、驗證、失敗,但這也是一個積累經驗的絕好機會。

  總結

  內存泄漏是個大而復雜的問題,即使是Java和.Net這樣有Gabarge Collection機制的環境,也存在著泄漏的可能,比如隱式內存泄漏。由于篇幅和能力的限制,本文只能對這個主題做一個粗淺的研究。其他的問題,比如多模塊下的泄漏檢測,如何在程序運行時對內存使用情況進行分析等等,都是可以深入研究的題目。如果您有什么想法,建議或發現了某些錯誤,歡迎和我交流。


posted on 2006-10-19 13:45 泡泡牛 閱讀(9171) 評論(2)  編輯 收藏 引用 所屬分類: Develop

評論

# re: 用BoundsChecker檢測內存泄漏 (zz)  2008-10-10 16:02 Pfeng

大俠,請問您對查找C#的內存泄漏是否有好的辦法?TKS!
MSN: P.feng@hotmail.com
  回復  更多評論    

# re: 用BoundsChecker檢測內存泄漏 (zz)  2008-12-03 15:53 紫羅

boundschecker支持什么編譯器呢?
  回復  更多評論    
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            日韩视频精品在线| 国产欧美不卡| 9久re热视频在线精品| 亚洲欧洲日本mm| 欧美另类一区| 亚洲欧美国产日韩天堂区| 亚洲一区二区三区四区视频| 国产精品扒开腿爽爽爽视频| 久久www成人_看片免费不卡| 久久久欧美精品| 一本色道久久综合亚洲精品高清 | 91久久香蕉国产日韩欧美9色| 欧美大片免费观看在线观看网站推荐| 亚洲看片免费| 午夜精品久久久久久久99热浪潮 | 国产精品二区在线| 久久精品中文字幕一区| 老司机精品福利视频| 亚洲影院污污.| 久久成人国产| 中文精品视频| 久久久久久一区二区| 亚洲校园激情| 国产精品制服诱惑| 亚洲国产婷婷| 亚洲欧美不卡| 日韩视频在线播放| 久久久久久久久久久一区 | 一区二区日韩精品| 午夜精品电影| 一区二区91| 久久香蕉国产线看观看网| 亚洲视频中文| 欧美va亚洲va国产综合| 欧美影片第一页| 欧美日韩国内自拍| 麻豆九一精品爱看视频在线观看免费| 欧美日韩免费观看一区| 蘑菇福利视频一区播放| 国产精品视频免费观看| 亚洲日韩第九十九页| 国模精品娜娜一二三区| 亚洲视频在线视频| 亚洲精品久久嫩草网站秘色 | 久久久久一区二区三区四区| 亚洲欧美另类中文字幕| 欧美日本韩国一区二区三区| 欧美99久久| 亚洲一区二区三区视频播放| 亚洲二区精品| 欧美国产综合一区二区| 欧美一区二区三区电影在线观看| 你懂的视频欧美| 美女久久一区| 久久一区二区精品| 国产日韩成人精品| 宅男噜噜噜66一区二区66| 亚洲欧洲精品一区二区三区| 久久久久网站| 欧美大片va欧美在线播放| 在线播放豆国产99亚洲| 久久精品视频va| 蜜桃伊人久久| 亚洲电影毛片| 欧美高清视频在线| 亚洲精品在线免费| 一区二区国产日产| 久久男女视频| 欧美一区二区免费视频| 国产欧美日韩不卡| 亚洲亚洲精品三区日韩精品在线视频 | 亚洲图中文字幕| 欧美日韩网址| 在线亚洲国产精品网站| 欧美亚洲色图校园春色| 国产日韩欧美夫妻视频在线观看| 亚洲免费在线观看视频| 久久久www免费人成黑人精品| 久久av资源网| 亚洲午夜激情| 国产精品亚洲欧美| 久久久久久久综合| 亚洲国产精品久久久| 日韩系列在线| 国产精品日韩一区二区| 久久久午夜视频| 亚洲精品一区二区三区99| 亚洲欧美日韩另类| 国外成人在线视频网站| 欧美 日韩 国产在线| 亚洲免费黄色| 久久亚洲精品中文字幕冲田杏梨| 91久久国产综合久久91精品网站 | 午夜精彩国产免费不卡不顿大片| 久久精品一区| 亚洲美女啪啪| 国产中文一区二区| 欧美精品九九| 欧美在线精品一区| 亚洲精选在线观看| 久久亚洲美女| 亚洲欧美第一页| 最近中文字幕日韩精品| 国产精品免费一区豆花| 可以免费看不卡的av网站| 亚洲一本视频| 亚洲精品乱码久久久久久按摩观| 欧美一区三区三区高中清蜜桃| 亚洲激情在线播放| 国产日韩精品一区二区三区在线| 欧美成人在线网站| 欧美一区日韩一区| 中文亚洲欧美| 亚洲精品你懂的| 欧美成人午夜| 久久欧美中文字幕| 羞羞答答国产精品www一本| 亚洲伦理一区| 亚洲国产高清在线| 国产一区在线视频| 国产精品热久久久久夜色精品三区 | 在线综合亚洲欧美在线视频| 欧美高清视频www夜色资源网| 欧美一区二区三区免费视| 亚洲美女av网站| 亚洲福利免费| 伊人久久婷婷| 韩日欧美一区二区| 国产一区久久| 国产一区视频网站| 国产一区日韩一区| 国产性猛交xxxx免费看久久| 国产精品高潮呻吟| 欧美日韩视频在线一区二区观看视频| 狂野欧美激情性xxxx欧美| 久久激情视频免费观看| 性久久久久久久久久久久| 亚洲性视频网站| 亚洲欧美日韩视频一区| 亚洲女爱视频在线| 亚洲欧美精品伊人久久| 亚洲欧美国产日韩中文字幕| 亚洲制服欧美中文字幕中文字幕| 亚洲视频电影图片偷拍一区| 一区二区三区久久| 一本色道综合亚洲| 亚洲一品av免费观看| 亚洲在线中文字幕| 欧美一区二区三区播放老司机 | 久久综合免费视频影院| 亚洲成人原创| 亚洲日本成人网| 99精品国产福利在线观看免费| 亚洲精品裸体| 亚洲午夜精品一区二区三区他趣 | 欧美日韩在线不卡一区| 国产精品99久久久久久有的能看 | 欧美成人精品一区二区三区| 免费毛片一区二区三区久久久| 久久精品国产96久久久香蕉| 久久一综合视频| 欧美成人激情视频| 亚洲欧洲日产国码二区| 99精品欧美一区二区三区综合在线| 日韩亚洲欧美中文三级| 亚洲欧美日本另类| 久久久夜精品| 欧美激情在线播放| 国产精品日日摸夜夜添夜夜av | 欧美激情在线有限公司| 国产精品v欧美精品v日韩| 国产一区二区三区四区五区美女 | 欧美激情欧美激情在线五月| 亚洲精选成人| 欧美尤物一区| 欧美国产成人在线| 国产日韩精品在线| 日韩亚洲不卡在线| 久久九九免费| 亚洲精选一区二区| 久久久久久91香蕉国产| 欧美区日韩区| 精品福利免费观看| 亚洲欧美高清| 亚洲第一色中文字幕| 亚洲一区二区三区精品视频| 美女日韩欧美| 国外成人网址| 午夜精彩国产免费不卡不顿大片| 免费亚洲电影在线| 亚洲影视在线| 欧美日韩一级黄| 亚洲激情一区二区三区| 久久av资源网站| 亚洲视频自拍偷拍| 欧美国产日韩一区二区在线观看| 国产亚洲欧美激情| 午夜精品久久久99热福利| 亚洲黄色免费网站| 久久久水蜜桃|