句柄泄漏调试经验

来源:互联网 发布:it就业培训学校 编辑:程序博客网 时间:2024/05/22 13:14

句柄泄漏检测-简单
在调试之前首先确定是不是真的发生了句柄泄漏,简单的检测方法是通过任务管理器来查看进程的句柄数是不是居高不下,任务管理器默认不显示句柄数,要查看进程的句柄数需要先切换到进程选项卡,然后单击“查看”菜单,选择“选择列”,然后勾选“句柄数”。

句柄泄漏检测-更多信息
任务管理器只能简单检测句柄数,如果要获得更详细的信息,可以使用Process Explorer(官方下载地址为http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx)通过Process Explorer可以查看进程句柄的类型和名字,如图所示:
通过任务管理器和Process Explorer检测句柄泄漏
可以通过这些详细信息来初步判断那个地方出了问题。

句柄泄漏检测和调试
Windbg提供了强大的扩展命令!htrace,即句柄跟踪(Handle Trace),可以通过操作系统来跟踪所有打开句柄或关闭句柄的调用以及相应的栈回溯。
在命令行下启动目标程序(源码下载),让后将Windbg附加到这个进程上,在Windbg输入”!htrace -?”,可以查看命令帮助。

我们需要先在Windbg中输入”!htrace -enable”来开启栈回溯,然后通过g命令来运行被调试的程序,等到程序运行结束时,再在Windbg中运行”!htrace”来观察和打开或关闭句柄有关的栈回溯信息,Windbg的调试日志如下:

// 发现部分RSS订阅工具显示代码的格式很混乱// RSS订阅读者可以通过阅读原文正常查看代码或者更换订阅工具0:001> !trace -?No export trace found0:001> !htrace -?!htrace [handle [max_traces]]!htrace -enable [max_traces]!htrace -disable!htrace -snapshot!htrace -diff0:001> !htrace -enableHandle tracing enabled.Handle tracing information snapshot successfully taken.0:001> g(130c.1558): Break instruction exception - code 80000003 (first chance)eax=7ffde000 ebx=00000000 ecx=00000000 edx=772bd23d esi=00000000 edi=00000000eip=77253540 esp=006ff8d0 ebp=006ff8fc iopl=0         nv up ei pl zr na pe nccs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246ntdll!DbgBreakPoint:77253540 cc              int     30:001> !htrace--------------------------------------Handle = 0x00000080 - CLOSEThread ID = 0x000017dc, Process ID = 0x0000130c 0x7726491c: ntdll!ZwClose+0x0000000c0x75476b1c: KERNELBASE!CloseHandle+0x0000002d0x76c2057f: kernel32!CloseHandleImplementation+0x0000003f*** WARNING: Unable to verify checksum for G:\W7Documents\Visual Studio 6.0\Projects\HLeak\Debug\HLeak.exe0x01201afb: HLeak!wmain+0x0000032b0x01202b68: HLeak!__tmainCRTStartup+0x000001a80x012029af: HLeak!wmainCRTStartup+0x0000000f0x76c21114: kernel32!BaseThreadInitThunk+0x0000000e0x7727b3f5: ntdll!__RtlUserThreadStart+0x000000700x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b--------------------------------------……省略N多行信息……--------------------------------------Handle = 0x00000030 - OPENThread ID = 0x000017dc, Process ID = 0x0000130c 0x77264b7c: ntdll!NtCreateThreadEx+0x0000000c0x7547bd01: KERNELBASE!CreateRemoteThreadEx+0x000001610x76c227bd: kernel32!CreateThreadStub+0x000000200x01201a5a: HLeak!wmain+0x0000028a0x01202b68: HLeak!__tmainCRTStartup+0x000001a80x012029af: HLeak!wmainCRTStartup+0x0000000f0x76c21114: kernel32!BaseThreadInitThunk+0x0000000e0x7727b3f5: ntdll!__RtlUserThreadStart+0x000000700x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b --------------------------------------Parsed 0x158 stack traces.Dumped 0x158 stack traces.

如何调试?
看起来输出信息过多,如果要一个一个去看哪些句柄没有CLOSE,那样工作量太大了。我们可以通过在Windbg中输入”!htrace -diff”来自动筛选出没有CLOSE的句柄的栈回溯信息:

0:001> !htrace -diffHandle tracing information snapshot successfully taken.0x158 new stack traces since the previous snapshot.Ignoring handles that were already closed...Outstanding handles opened since the previous snapshot:--------------------------------------Handle = 0x000003a4 - OPENThread ID = 0x000012bc, Process ID = 0x0000130c 0x772651ec: ntdll!ZwOpenProcessToken+0x0000000c0x7547748f: KERNELBASE!OpenProcessToken+0x000000140x0120237e: HLeak!CServer::GetToken+0x0000007e0x01201da9: HLeak!CServer::GetSID+0x000000390x012015d3: HLeak!ThreadWorker+0x000000c30x76c21114: kernel32!BaseThreadInitThunk+0x0000000e0x7727b3f5: ntdll!__RtlUserThreadStart+0x000000700x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b--------------------------------------……省略N多行信息……--------------------------------------Handle = 0x0000003c - OPENThread ID = 0x0000168c, Process ID = 0x0000130c 0x772649fc: ntdll!NtCreateEvent+0x0000000c0x772495d7: ntdll!RtlpCreateCriticalSectionSem+0x0000001a0x772495ad: ntdll!RtlpWaitOnCriticalSection+0x000000740x7724fb56: ntdll!RtlEnterCriticalSection+0x000001500x7727b479: ntdll!LdrpInitializeThread+0x000000c60x7727b298: ntdll!_LdrpInitialize+0x000001ad0x7727b2c5: ntdll!LdrInitializeThunk+0x00000010--------------------------------------Displayed 0x68 stack traces for outstanding handles opened since the previous snapshot.

可以通过这些信息来帮助对句柄泄漏的调试过程。

句柄泄漏回避策略

使用RAII(Resource Acquisition Is Initialization)策略,这个就不多说了,STL里面的auto_ptr就使用了这样了的策略。


http://www.programlife.net/handle-leak-debug-skill.html

0 0
原创粉丝点击