开发者社区> xumaojun> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

句柄泄漏调试经验

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

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

句柄泄漏检测-更多信息
任务管理器只能简单检测句柄数,如果要获得更详细的信息,可以使用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

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
实用调试技巧
实用调试技巧
5 0
ADC调试经验分享
本文介绍 ADC调试经验分享
399 0
ADC调试经验分享
本文主要是关于ADC调试经验分享,希望对大家能有所帮助。
396 0
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     如果你不喜欢英文,那就可以看下面我蹩脚的解释了。
787 0
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     如果你不喜欢英文,那就可以看下面我蹩脚的解释了。
985 0
puppet常用调试命令
yum快速部署puppet测试环境(C/S端) rpm -ivh  http://yum.puppetlabs.com/puppetlabs-release-el-7.noarch.rpm yum ruby ruby-libs ruby-shadow puppet puppet-server f...
1365 0
GCC调试基础知识
The History of GCC   --------------------------------------------------------------------------------   1984年,Richard Stallman发起了自由软件运动,GNU (Gnu's Not Unix)项目应运而生,3年后,最初版的GCC横空出世,成为第一款可移植、可优化、支持ANSI C的开源C编译器。
485 0
调试宏
比如:#define  DebugShowMessage( Msg )   ShowMessage (AnsiString(Msg)) 非常方便
448 0
+关注
xumaojun
乐于学习与分析
1078
文章
95
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载