windbg !htrace 学习总结

来源:互联网 发布:c语言小游戏源代码 编辑:程序博客网 时间:2024/05/29 17:03

windbg-!htrace(跟踪句柄泄漏)

http://blog.csdn.net/hgy413/article/details/7631187

!htrace
!htrace(Handle Trace) 扩展用于显示一个或多个句柄的堆栈回溯信息。

直接用!htrace -?可以看到简单使用说明:

0:000> !htrace -?  !htrace [handle [max_traces]]  !htrace -enable [max_traces]  !htrace -disable  !htrace -snapshot  !htrace -diff  

Handle
指定要显示堆栈回溯的句柄。如果Handle 为0 或者省略,则显示进程中所有句柄的堆栈回溯。
Process
(仅内核模式) 指定要显示句柄的进程。如果Process 为0或者省略,则使用当前进程。用户模式下总是使用当前进程。
Max_Traces
指定要显示的堆栈回溯的最大层数。用户模式下如果省略该参数,则显示目标进程中的所有堆栈回溯。
-enable
(仅用户模式) 启用句柄跟踪,并且为-diff 选项使用的初始状态产生第一次句柄信息的快照。
-snapshot
(仅用户模式) 抓取当前的句柄信息的快照用作-diff 选项的初始状态。.
-diff
(仅用户模式) 将当前的句柄信息和上一次句柄快照的信息进行对比。显示所有仍然打开的句柄。
-disable
(仅用户模式;仅Windows Server 2003和之后的系统) 禁止句柄跟踪。在Windows XP中,只有结束目标进程才能禁用句柄跟踪。
-?
在调试器命令窗口中显示一些简要的帮助文本。
首先需要用!htrace -enable来告诉操作系统启用栈回溯(这是前提)

!htrace -snapshot  !htrace -diff  0:000> !htrace -enable  Handle tracing enabled.  Handle tracing information snapshot successfully taken.  

可以看到,-enable是一个两步操作,首先,启动栈回溯(Handle tracing enabled),

然后,它根据句柄来抓取进程当前状态的快照(Handle tracing information snapshot successfully taken.)
在栈回溯被启用后,windows将立即开始记录所有的句柄创建调用和句柄删除调用,在下一次抓取快照时(-snapshot),!htrace将向操作系统查询所有句柄
创建调用和句柄删除调用的栈回溯,并且把它们显示出来,
这时直接用!htrace会输出以下内容:
0:001> !htrace  --------------------------------------  Handle = 0x000007bc - CLOSE  Thread ID = 0x000014fc, Process ID = 0x000013f0    0x7c8135dd: kernel32!GetLongPathNameW+0x00000249  0x7854287c: MSVCR90!_check_manifest+0x0000009c  0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e  0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e  0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014  0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x00000344  0x7c93fbdc: ntdll!LdrpInitializeProcess+0x0000114b  0x7c93fad7: ntdll!_LdrpInitialize+0x00000183  0x7c92e457: ntdll!KiUserApcDispatcher+0x00000007  --------------------------------------  Handle = 0x000007bc - OPEN  Thread ID = 0x000014fc, Process ID = 0x000013f0    0x7c80ef97: kernel32!FindFirstFileW+0x00000016  0x7c8135c5: kernel32!GetLongPathNameW+0x00000231  0x7854287c: MSVCR90!_check_manifest+0x0000009c  0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e  0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e  0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014  0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x00000344  0x7c93fbdc: ntdll!LdrpInitializeProcess+0x0000114b  0x7c93fad7: ntdll!_LdrpInitialize+0x00000183  --------------------------------------  Handle = 0x000007c0 - CLOSE  Thread ID = 0x000014fc, Process ID = 0x000013f0    0x7c8135dd: kernel32!GetLongPathNameW+0x00000249  0x7854287c: MSVCR90!_check_manifest+0x0000009c  0x78542c22: MSVCR90!__CRTDLL_INIT+0x0000008e  0x78542d5e: MSVCR90!_CRTDLL_INIT+0x0000001e  0x7c92118a: ntdll!LdrpCallInitRoutine+0x00000014  0x7c93b5d2: ntdll!LdrpRunInitializeRoutines+0x000003  .........................  


格式一般是句柄值,进程线程, OPEN表示打开句柄的栈回溯,CLOSE表示关闭句柄的栈回溯,那么关键是要找到那些栈回溯打开了句柄,却没有相应的栈回溯来关闭句柄,这可以通过!htrace -diff来实现:

0:000> !htrace -diff  Handle tracing information snapshot successfully taken.  0xfa new stack traces since the previous snapshot.  Ignoring handles that were already closed...  Outstanding handles opened since the previous snapshot:  --------------------------------------  Handle = 0x000005b0 - OPEN  Thread ID = 0x000007f4, Process ID = 0x000013f0    0x00401657: test1!CServer::GetToken+0x00000047  0x0040136f: test1!CServer::GetSID+0x0000001f  0x004010de: test1!ThreadWorker+0x0000007e  0x7c80b729: kernel32!BaseThreadStart+0x00000037  --------------------------------------  Handle = 0x000005b4 - OPEN  Thread ID = 0x00000c34, Process ID = 0x000013f0    0x00401657: test1!CServer::GetToken+0x00000047  0x0040136f: test1!CServer::GetSID+0x0000001f  0x004010de: test1!ThreadWorker+0x0000007e  0x7c80b729: kernel32!BaseThreadStart+0x00000037  --------------------------------------  Handle = 0x000005b8 - OPEN  Thread ID = 0x00001650, Process ID = 0x000013f0    0x00401657: test1!CServer::GetToken+0x00000047  

很明显了,我们看到在GetToken中有句柄未关闭,所以在使用!htrace时采用的步骤一般是:

1. 在重现泄漏问题之前,启用句柄跟踪(!htrace -enable)

2.执行重现过程,并且让进程句柄泄漏

3.通过!htrace -diff来找出有问题的栈

自己写了下DML方便使用:

.printf "\n\nfor trace handle leak\n"  .block  {      as ${/v:ScriptName} c:\\cmdtree\\script\\User-Mode\\traceHandle.txt  }    .printf /D "<link cmd=\"!htrace -enable;ad ${/v:ScriptName};$$><${ScriptName}\">trace handle :<col fg=\"changed\"bg=\"wbg\"><b>snap-enable</b></col></link>\n\n"  .printf /D "<link cmd=\"!htrace -snapshot;ad ${/v:ScriptName};$$><${ScriptName}\">trace handle :<col fg=\"changed\"bg=\"wbg\"><b>snap-snapshot</b></col></link>\n\n"  .printf /D "<link cmd=\".echo you should get snapshot more than twice!!!!!!!!!!!!!!!!!!!!!!!!!;!htrace -diff;ad ${/v:ScriptName};$$><${ScriptName}\"\n\n>trace handle :<col fg=\"changed\"bg=\"wbg\"><b>diff</b></col></link>\n\n"  

========

用windbg的!htrace定位句柄泄露  


http://chenkegarfield.blog.163.com/blog/static/62330008201192122745542/
http://blogs.msdn.com/b/ntdebugging/archive/2007/09/14/talkbackvideo-understanding-handle-leaks-and-how-to-use-htrace-to-find-them.aspx
链接是老外的一篇文章,简单介绍了如何运用windbg中的htrace定位程序中的句柄泄露问题,同时附有一个教学视频。下面是对应的中文解释。
1、用c++写一个句柄泄露的样例程序:


#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)找到windbg安装目录下的gflags.exe工具,该工具可用来打开windows自带的一些调试选项,具体gflags.exe的详细使用可以查看windbg帮助;


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


这里我们设置勾上application verifiwer,该工具主要可用来对程序做一些稳定性的检测,本次调试主要用于保存栈的相关信息。同时设置stack backtrace即栈的大小为10.


2)运行windbg,打开第一步编译的程序,并使其跑起来;此时你查看任务管理器中的句柄信息,会发现相应进程句柄一直在增加。


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


3)windbg用ctrl+break命令中断进程运行,用!htrace -enable命令开启句柄检测;htrace提供了进行句柄相关检测的命令,可查看windbg帮助。


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


同时用g命令让程序运行。


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


4)再次中断进程,使用!htrace -snapshot命令,获得此时进程句柄的镜像。并再次让程序运行。


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


5)第三次中断进程运行,我们再使用!htrace -diff命令获得当前句柄状态与第4步 snapshot镜像句柄的差异;


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


我们可以发现:新增很多打开的句柄,平常情况下这些打开的句柄有可能不是泄露,需要具体分析,但是本次示例程序太简单,所以刚好所有打开的句柄都属于泄露的。


6)我们使用lsa 传递指定位置对应的代码,lsa   handlew2!fun4+0x0000002e


用windbg的!htrace定位句柄泄露 - chenkegarfield - chenkegarfield的博客


到这里,我们就找到了泄露句柄的函数。


Windbg Debugger’s !htrace extension is very handy to debug handle leak.


The process essentially boils down to the following simple steps:


1.       Enable trace
2.       Take a snapshot
3.       Run scenario
4.       Show the diff


On step 4, !htrace will show all the extra opened handles after the last snapshot, along with the callstack if available. This greatly helps to debug what handles are leak, and by whom.


Like any other resource leak detection tool, there will be false positives. You need to understand what is a real leak, and what is just a transient allocation.
 
!htrace


The !htrace extension displays stack trace information for one or more handles.


Syntax


User-Mode Syntax


!htrace [Handle [Max_Traces]] 
!htrace -enable [Max_Traces]
!htrace -snapshot
!htrace -diff
!htrace -disable
!htrace -? 


Kernel-Mode Syntax


!htrace [Handle [Process [Max_Traces]]] 
!htrace -? 


Parameters


Handle
Specifies the handle whose stack trace will be displayed. If Handle is 0 or omitted, stack traces for all handles in the process will be displayed.
Process
(Kernel mode only) Specifies the process whose handles will be displayed. If Process is 0 or omitted, then the current process is used. In user mode, the current process is always used.
Max_Traces
Specifies the maximum number of stack traces to display. In user mode, if this parameter is omitted, then all the stack traces for the target process will be displayed.
-enable
(User mode only) Enables handle tracing and takes the first snapshot of the handle information to use as the initial state by the -diff option.
-snapshot
(User mode only) Takes a snapshot of the current handle information to use as the initial state by the-diff option.
-diff
(User mode only) Compares current handle information with the last snapshot of handle information that was taken. Displays all handles that are still open.
-disable
(User mode only; Windows Server 2003 and later only) Disables handle tracing. In Windows XP, handle tracing can be disabled only by terminating the target process.
-?
Displays some brief Help text for this extension in the Debugger Command window.
DLL


Windows NT 4.0
Unavailable
Windows 2000
Unavailable
Windows XP and later
Kdexts.dll 
Ntsdexts.dll
Comments


Before !htrace can be used, Application Verifier must be activated for the target process, and theDetect invalid handle usage option must be selected. By activating Application Verifier, stack trace information is saved each time the process opens a handle, closes a handle, or references an invalid handle. It is this stack trace information that !htrace displays. For more information, seeApplication Verifier.


The following example displays information about all handles in process 0x81400300:


kd> !htrace 0 81400300
Process 0x81400300
ObjectTable 0xE10CCF60


--------------------------------------
Handle 0x7CC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
--------------------------------------
Handle 0x7CC - OPEN:
0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE23B2: KERNEL32!CreateSemaphoreA+0x66
0x010011C5: badhandle!main+0x45
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
--------------------------------------
Handle 0x7DC - BAD REFERENCE:
0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
--------------------------------------
Handle 0x7DC - CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
--------------------------------------
Handle 0x7DC - OPEN:
0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D


--------------------------------------
Parsed 0x6 stack traces.
Dumped 0x5 stack traces.
========

Use !htrace to debug handle leak

https://blogs.msdn.microsoft.com/junfeng/2008/04/21/use-htrace-to-debug-handle-leak/
avatar of junfengJunfeng ZhangApril 21, 20083
Share
0
0
Windbg Debugger’s !htrace extension is very handy to debug handle leak.


The process essentially boils down to the following simple steps:


1.       Enable trace


2.       Take a snapshot


3.       Run scenario


4.       Show the diff


On step 4, !htrace will show all the extra opened handles after the last snapshot, along with the callstack if available. This greatly helps to debug what handles are leak, and by whom.


Like any other resource leak detection tool, there will be false positives. You need to understand what is a real leak, and what is just a transient allocation.


!htrace


The !htrace extension displays stack trace information for one or more handles.


Syntax


User-Mode Syntax


!htrace [Handle [Max_Traces]] 
!htrace -enable [Max_Traces]
!htrace -snapshot
!htrace -diff
!htrace -disable
!htrace -? 


Kernel-Mode Syntax


!htrace [Handle [Process [Max_Traces]]] 
!htrace -? 


Parameters


Handle


Specifies the handle whose stack trace will be displayed. If Handle is 0 or omitted, stack traces for all handles in the process will be displayed.


Process


(Kernel mode only) Specifies the process whose handles will be displayed. If Process is 0 or omitted, then the current process is used. In user mode, the current process is always used.


Max_Traces


Specifies the maximum number of stack traces to display. In user mode, if this parameter is omitted, then all the stack traces for the target process will be displayed.


-enable


(User mode only) Enables handle tracing and takes the first snapshot of the handle information to use as the initial state by the -diff option.


-snapshot


(User mode only) Takes a snapshot of the current handle information to use as the initial state by the -diff option.


-diff


(User mode only) Compares current handle information with the last snapshot of handle information that was taken. Displays all handles that are still open.


-disable


(User mode only; Windows Server 2003 and later only) Disables handle tracing. In Windows XP, handle tracing can be disabled only by terminating the target process.


-?


Displays some brief Help text for this extension in the Debugger Command window.


DLL


Windows NT 4.0


Unavailable


Windows 2000


Unavailable


Windows XP and later


Kdexts.dll 
Ntsdexts.dll


Comments


Before !htrace can be used, Application Verifier must be activated for the target process, and the Detect invalid handle usage option must be selected. By activating Application Verifier, stack trace information is saved each time the process opens a handle, closes a handle, or references an invalid handle. It is this stack trace information that !htrace displays. For more information, see Application Verifier.


The following example displays information about all handles in process 0x81400300:


kd> !htrace 0 81400300
Process 0x81400300
ObjectTable 0xE10CCF60


————————————–
Handle 0x7CC – CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
————————————–
Handle 0x7CC – OPEN:
0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE23B2: KERNEL32!CreateSemaphoreA+0x66
0x010011C5: badhandle!main+0x45
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
————————————–
Handle 0x7DC – BAD REFERENCE:
0x8018F709: ntoskrnl!ExMapHandleToPointerEx+0xEA
0x801E10F2: ntoskrnl!ObReferenceObjectByHandle+0x12C
0x801902BE: ntoskrnl!NtSetEvent+0x6C
0x80154965: ntoskrnl!_KiSystemService+0xC4
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
————————————–
Handle 0x7DC – CLOSE:
0x8018FCB9: ntoskrnl!ExDestroyHandle+0x103
0x801E1D12: ntoskrnl!ObpCloseHandleTableEntry+0xE4
0x801E1DD9: ntoskrnl!ObpCloseHandle+0x85
0x801E1EDD: ntoskrnl!NtClose+0x19
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D
————————————–
Handle 0x7DC – OPEN:
0x8018F44A: ntoskrnl!ExCreateHandle+0x94
0x801E3390: ntoskrnl!ObpCreateUnnamedHandle+0x10C
0x801E7317: ntoskrnl!ObInsertObject+0xC3
0x77DE265C: KERNEL32!CreateEventA+0x66
0x010011A0: badhandle!main+0x20
0x010012C1: badhandle!mainCRTStartup+0xE3
0x77DE0B2F: KERNEL32!BaseProcessStart+0x3D


————————————–
Parsed 0x6 stack traces.
Dumped 0x5 stack traces.


Additional Information


For information about handles, see the Microsoft Windows SDK documentation and Microsoft Windows Internals by Mark Russinovich and David Solomon. To display further information about a specific handle, use the !handle extension.


2007 Microsoft Corporation
Send feedback on this topic


Tags Debugging
Comments (3)


Name * 


Email * 


Website 


Post Comment
Microsoft news and tips &raquo; Use !htrace to debug handle leak
April 21, 2008 at 12:01 pm
PingBack from http://microsoftnews.askpcdoc.com/?p=3494


Reply
Koby Kahane
April 21, 2008 at 2:30 pm
!htrace is an awesome extension, easily one of my favorites.


I recall debugging a registry handle leak in third-party code and a desktop handle leak in in-house code, among other things, using this great tool.


A great example of the added value of dbgeng extensions given to Windbg over alternative debuggers such Ollydbg, Visual Studio, etc.


I think that in a more general sense, some great capabilities of App Verifier are unknown to the developer community at large and should be evangelized more.


Hopefully options providing finer granularity will be added to the !htrace extension command in future DTW releases, allowing filtering handles based on their type and filtering stack traces based on the contents, !findstack style, and so on.


Reply
Norman Diamond
April 21, 2008 at 8:58 pm
The link to


mk:@MSITStore:C:debuggersdebugger.chm::/hh/Debugger/AppVerif2_437533d6-daa8-4fe9-90da-a7717ebc9683.xml.htm


doesn’t work in Internet Explorer, even though I have the MSDN library installed.


Reply
========

Htrace查找handle泄露点操作步骤

http://blog.csdn.net/tpriwwq/article/details/9082709


1. 使用Windbg -File-OpenExecutable,打开要调试exe.


     程序启动后,系统会暂停程序一次.这个是正常的.


2. 启用htrace:  (在windbg的命令窗口中输入)!htrace -enable


3. 运行程序: (在windbg的命令窗口中输入)g


4.某个时刻创建一次句柄快照:(在windbg的命令窗口中输入)!htrace -snapshot


观察到handle增长,暂停进程(Debug - Break)


继续运行后进行一次句柄快照对比:(在windbg的命令窗口中输入)!htrace -diff


5.使用(在windbg的命令窗口中输入)!htrace ***(此处为handle的地址),即可跟踪到handle泄露点


6.根据handle的输出信息,如果有源码,则可以使用(在windbg的命令窗口中输入)lsa 传递指定位置对应的代码,定位到handle泄露点


 ----------------------


个人体会:


通过Htrace 检测到的Handle不一定就是泄露的Handle,在跟踪中常碰到句柄增长了1个,通过


Htrace -diff 获取一大堆的情形。所以要准确定位到泄漏Handle,还需要结合编码进行分析。
 


------------------------------------------------------------------------------------


 相对于Htrace,  使用ProcessExplorer和Handle工具也可以查找handle泄露点.


1.ProcessExplorer


为便于观察,需对ProcessExplorer进行设置


     设置 1)view- show unnamed handle。。。; //显示handle


               2 ) view - ShowLowerPane                          


               3)如果想看实时变化情况,调整   options - Difference Highlight Duration,调整为9s


               4)  如果想看某一时间段的变化, view - Update Speed 改为 Paused,按 F5获取列表,运行一段时间后,


再次按F5获取新的对象列表.


2. Handle


cmd输入: Handle -s -p (Processname | ProcessID)




========

windbg检测句柄泄露(定位到具体代码)

http://blog.csdn.net/yockie/article/details/40603511


1.构造一个测试用例




[cpp] view plain copy 在CODE上查看代码片派生到我的代码片
#include "stdafx.h"  
#include <Windows.h>  
  
void NormalFunc()  
{  
    HANDLE hEvent;  
    hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);  
    CloseHandle(hEvent);  
}  
  
void HandleLeakFunc()  
{  
    HANDLE hEvent;  
    hEvent = CreateEvent(NULL,TRUE,TRUE,NULL);  
    //CloseHandle(hEvent);      //有句柄泄露  
}  
  
int main()  
{  
    while(1)  
    {  
        NormalFunc();  
        HandleLeakFunc();  
        Sleep(200);  
    }  
  
    return 0;  
}  


2.windbg调试
(1)运行windbg,首先确定符号表地址填写OK了。


(2)我们选择"Open Executable"再选择上述测试用例生成的exe,可能在实际工程中经常是"Attach to a process"。再看任务管理器会发现这个进程的句柄数飙升:


(3)windbg用ctrl+break命令中断进程运行,用!htrace -enable命令开启句柄检测;htrace命令提供了进行句柄检测相关的命令,可查看windbg帮助,如图:




(4)再使用!htrace -snapshot命令,获得此时进程句柄的镜像。让程序继续运行。


(5)中断进程运行,使用!htrace -diff命令获得当前句柄状态与第4步 snapshot镜像句柄的差异;


(6)输出很多打开的句柄,需要具体情况具体分析,最好对照代码来看。这里是测试,所以比较简单,一眼就看出来了。


(7)使用lsa 传递指定位置对应的代码,lsa Lab2010_2!HandleLeakFunc+0x00000012




总结一下,就是3个命令:


!htrace -enable


!htrace -snapshot


//do something


!htrace -diff


========

列举所有Handle(句柄)以及查看Handle 信息

http://wingeek.blog.51cto.com/1226974/274066/
WinDBG的 !handle 命令可以让你方便调试句柄(handle)。
查看进程内所有句柄, 输入命令行
0:014> !handle
Handle 4
  Type          Directory
Handle 8
  Type          Process
Handle c
  Type          Key
Handle 10
  Type          Mutant
Handle 14
  Type          ALPC Port
Handle 18
  Type          Key
Handle 1c
  Type          Event
Handle 20
  Type          Key
 ... (省略)
Handle 7e0
  Type          Mutant
392 Handles
Type            Count
None            17
Event           134
Section         47
File            35
Directory       3
Mutant          34
WindowStation   2
Semaphore       24
Key             47
Token           1
Process         3
Thread          27
Desktop         1
IoCompletion    4
Timer           5
Job             1
KeyedEvent      1
TpWorkerFactory 6


从WinDBG输出结果我们可以看到所有句柄的类型和值,以及统计信息(一共392个handle,其中有35个文件句柄,47个注册表句柄 .... )。
如果想查看某个句柄的详细信息, 可以用命令:
0:014> !handle 0x5c8 f
Handle 5c8
  Type          Key
  Attributes    0
  GrantedAccess 0x20019:
         ReadControl
         QueryValue,EnumSubKey,Notify
  HandleCount   2
  PointerCount  3
  Name          \REGISTRY\USER\S-1-5-21-2127521184-1604012920-1887927527-2966534\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts
  Object Specific Information
    Key last write time:  16:52:14. 5/20/2009
    Key name FileExts
0x5c8 是句柄的值, 参数f 表示显示全部信息。 我们可以看到句柄0x5c8 是注册表句柄,路径为\REGISTRY\USER\S-1-5-21-2127521184-1604012920-1887927527-2966534\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts。
值得一提的是,WinDBG 还提供了!htrace 命令,可以很方便来用检查句柄泄露(Handle Leak), 下次再写篇blog 专门介绍 !htrace 。
========
0 0
原创粉丝点击