同僚介紹了一篇調試句柄洩露的blog文章,今天有空看了一下,這家夥用視訊的方式錄下整個調試的過程,學習一目了然,真是有心。鑒于學習的過程總結一下能加深記憶,是以我這裡做個記錄,感興趣的朋友可以看這裡:
http://blogs.msdn.com/ntdebugging/archive/2007/09/14/talkbackvideo-understanding-handle-leaks-and-how-to-use-htrace-to-find-them.aspx如果你不喜歡英文,那就可以看下面我蹩腳的解釋了。
1、用c++寫一個句柄洩露的樣例程式:
#include "stdafx.h"
#include <windows.h>
void fun1(void);
void fun2(void);
void fun3(void);
void fun4(void);
int main(int argc, char* argv[])
{
while(1)
{
fun1();
fun2();
Sleep(100);
}
return 0;
}
void fun1(void)
fun3();
void fun2(void)
fun4();
void fun3(void)
HANDLE hEvent;
hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);
CloseHandle(hEvent);
void fun4(void)
HANDLE hEvent2;
hEvent2 = CreateEvent(NULL,TRUE,TRUE,NULL);//這裡隻打開但是沒關閉句柄
代碼非常簡單,明眼人一看就能看出哪裡有問題,那麼程式編譯後用windbg怎麼調出來呢?
2、windbg調試
1)找到windbgs安裝目錄下的gflags.exe工具,該工具可用來打開windows自帶的一些調試選項,具體gflags.exe的詳細使用可以檢視windbg幫助;

這裡我們設定勾上application verifiwer,該工具主要可用來對程式做一些穩定性的檢測,本次調試主要用于儲存棧的相關資訊。同時設定stack backtrace即棧的大小為10.
2)運作windbg,打開第一步編譯的程式,并使其跑起來;此時你檢視任務管理器中的句柄資訊,會發行相應程序句柄一直在增加。
3)windbg用ctrl+break指令中斷程序運作,用!htrace -enable指令開啟句柄檢測;htrace提供了進行句柄相關檢測的指令,可檢視windbg幫助。
同時用g指令讓程式運作。
4)再次中斷程序,使用!htrace -snapshot指令,獲得此時程序句柄的鏡像。并再次讓程式運作。
5)第三次中斷程序運作,我們再使用!htrace -diff指令獲得目前句柄狀态與第4步 snapshot鏡像句柄的差異;
我們可以發現:新增很多打開的句柄,平常情況下這些打開的句柄有可能不是洩露,需要具體分析,但是本次示例程式太簡單,是以剛好所有打開的句柄都屬于洩露的。
6)我們使用lsa 傳遞指定位置對應的代碼,lsa handlew2!fun4+0x0000002e
到這裡,我們就找到了洩露句柄的函數,真是神奇啊。