句柄泄漏调试经验

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

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

句柄泄漏检测-更多信息
任务管理器只能简单检测句柄数,如果要获得更详细的信息,可以使用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 found
0:001> !htrace -?
!htrace [handle [max_traces]]
!htrace -enable [max_traces]
!htrace -disable
!htrace -snapshot
!htrace -diff
0:001> !htrace -enable
Handle 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=00000000
eip=77253540 esp=006ff8d0 ebp=006ff8fc iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77253540 cc              int     3
0:001> !htrace
--------------------------------------
Handle = 0x00000080 - CLOSE
Thread ID = 0x000017dc, Process ID = 0x0000130c
 
0x7726491c: ntdll!ZwClose+0x0000000c
0x75476b1c: KERNELBASE!CloseHandle+0x0000002d
0x76c2057f: kernel32!CloseHandleImplementation+0x0000003f
*** WARNING: Unable to verify checksum for G:\W7Documents\Visual Studio 6.0\Projects\HLeak\Debug\HLeak.exe
0x01201afb: HLeak!wmain+0x0000032b
0x01202b68: HLeak!__tmainCRTStartup+0x000001a8
0x012029af: HLeak!wmainCRTStartup+0x0000000f
0x76c21114: kernel32!BaseThreadInitThunk+0x0000000e
0x7727b3f5: ntdll!__RtlUserThreadStart+0x00000070
0x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b
--------------------------------------
……省略N多行信息……
--------------------------------------
Handle = 0x00000030 - OPEN
Thread ID = 0x000017dc, Process ID = 0x0000130c
 
0x77264b7c: ntdll!NtCreateThreadEx+0x0000000c
0x7547bd01: KERNELBASE!CreateRemoteThreadEx+0x00000161
0x76c227bd: kernel32!CreateThreadStub+0x00000020
0x01201a5a: HLeak!wmain+0x0000028a
0x01202b68: HLeak!__tmainCRTStartup+0x000001a8
0x012029af: HLeak!wmainCRTStartup+0x0000000f
0x76c21114: kernel32!BaseThreadInitThunk+0x0000000e
0x7727b3f5: ntdll!__RtlUserThreadStart+0x00000070
0x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b
 
--------------------------------------
Parsed 0x158 stack traces.
Dumped 0x158 stack traces.

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

0:001> !htrace -diff
Handle 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 - OPEN
Thread ID = 0x000012bc, Process ID = 0x0000130c
 
0x772651ec: ntdll!ZwOpenProcessToken+0x0000000c
0x7547748f: KERNELBASE!OpenProcessToken+0x00000014
0x0120237e: HLeak!CServer::GetToken+0x0000007e
0x01201da9: HLeak!CServer::GetSID+0x00000039
0x012015d3: HLeak!ThreadWorker+0x000000c3
0x76c21114: kernel32!BaseThreadInitThunk+0x0000000e
0x7727b3f5: ntdll!__RtlUserThreadStart+0x00000070
0x7727b3c8: ntdll!_RtlUserThreadStart+0x0000001b
--------------------------------------
……省略N多行信息……
--------------------------------------
Handle = 0x0000003c - OPEN
Thread ID = 0x0000168c, Process ID = 0x0000130c
 
0x772649fc: ntdll!NtCreateEvent+0x0000000c
0x772495d7: ntdll!RtlpCreateCriticalSectionSem+0x0000001a
0x772495ad: ntdll!RtlpWaitOnCriticalSection+0x00000074
0x7724fb56: ntdll!RtlEnterCriticalSection+0x00000150
0x7727b479: ntdll!LdrpInitializeThread+0x000000c6
0x7727b298: ntdll!_LdrpInitialize+0x000001ad
0x7727b2c5: 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

相关文章
|
28天前
|
监控 NoSQL Linux
深入Linux内存泄漏排查:Valgrind与系统工具的联合应用
深入Linux内存泄漏排查:Valgrind与系统工具的联合应用
79 0
|
7月前
|
开发框架 .NET API
调试实战——PInvoke导致栈破坏
.net 程序也能崩溃?本文记录了 PInvoke 导致的栈破坏的排查过程
|
云安全 监控 安全
只想着一直调用一直爽, 那API凭证泄漏风险如何破?
如今各家云厂商都通过给用户提供API调用的方式来实现一些自动化编排方面的需求。为了解决调用API过程中的通信加密和身份认证问题,大多数云厂商会使用同一套技术方案—基于非对称密钥算法的鉴权密钥对,这里的“密钥对”即API凭证,是云上用户调用云服务API、访问云上资源的唯一身份凭证。
2286 0
|
Java 程序员 Android开发
Android内存泄漏的简单检查与分析方法
内存泄漏问题大约是Android开发者最烦恼的问题之一了,项目中连续遇到几个内存泄漏问题,这里简单总结下检查分析内存泄漏的一些工具与方法。
1596 0
|
C++ Windows
windbg调试实例(4)--句柄泄露[转]
同事介绍了一篇调试句柄泄露的blog文章,今天有空看了一下,这家伙用视频的方式录下整个调试的过程,学习一目了然,真是有心。鉴于学习的过程总结一下能加深记忆,所以我这里做个记录,感兴趣的朋友可以看这里:http://blogs.msdn.com/ntdebugging/archive/2007/09/14/talkbackvideo-understanding-handle-leaks-and-how-to-use-htrace-to-find-them.aspx     如果你不喜欢英文,那就可以看下面我蹩脚的解释了。
1292 0
|
C++ Windows
windbg调试实例(4)--句柄泄露
同事介绍了一篇调试句柄泄露的blog文章,今天有空看了一下,这家伙用视频的方式录下整个调试的过程,学习一目了然,真是有心。鉴于学习的过程总结一下能加深记忆,所以我这里做个记录,感兴趣的朋友可以看这里:http://blogs.msdn.com/ntdebugging/archive/2007/09/14/talkbackvideo-understanding-handle-leaks-and-how-to-use-htrace-to-find-them.aspx     如果你不喜欢英文,那就可以看下面我蹩脚的解释了。
867 0
|
Windows Go
堆内存破坏检测实战--附完整调试过程
首先解释一下,什么是堆内存? 堆是一种常见的内存管理器,应用程序通过堆来动态地分配和释放内存,通常使用堆的情况是无法预先知道所需要的内存大小,或者申请内存太大,无法通过栈内存来自动分配,下面让我们再来看一段英文解释。
1245 0
|
Shell 测试技术 Android开发

热门文章

最新文章