(Windbg调试六)c++句柄泄漏问题定位

c++句柄泄漏问题定位


     Windows内核中定义了一组操作系统特有的对象类型,包括文件对象,线程对象,Event对象等。要使用某种对象类型,必须首先生成这种对象类型的一个实例,以事件对象为例,调用CreateEvent可以创建或者打开一个现有的Event,在该函数内部,它调用了内核接口来创建一个事件对象,并且分配了相应的内存来容纳这个对象实例,最后将获得的结果句柄返回给开发人员,开发人员通过句柄来访问在内核中创建的事件对象实例。当我们使用完这个事件对象后,需要庀这个句柄,这样windows操作系统就可以正确地递减对这个对象的引用计数,并且当引用计数为0释放内存。

     显然,如果忘记了关闭这个句柄,这块内存也将不会被释放,这个问题就是句柄泄漏。我们可以通过任务管理器直观地看到某一个应用程序所使用的句柄数量:
在这里插入图片描述
     对应用程序进行不同的操作,对比两个操作的句柄数,可以初步判定该程序是否存在句柄泄漏。当通过任务管理器确认程序存在句柄泄漏后,我们就需要定位到具体的代码处,Windbg可以帮助我们完成这个任务。

     首先简单介绍一下!htrace命令,该命令用于显示一个或多个句柄的堆栈回溯信息。在Windbg中输入!htrace ? 查看该命令的参数:
在这里插入图片描述
handle
指定要显示堆栈回溯的句柄。如果Handle 为0 或者省略,则显示进程中所有句柄 的堆栈回溯
Max_Traces
指定要显示的堆栈回溯的最大层数。用户模式下如果省略该参数,则显示目标进程中的所有堆栈回溯。
-enable
(仅用户模式) 启用句柄跟踪,并且为-diff 选项使用的初始状态产生第一次句柄信息的快照。
-snapshot
(仅用户模式) 抓取当前的句柄信息的快照用作-diff 选项的初始状态。.
-diff
(仅用户模式) 将当前的句柄信息和上一次句柄快照的信息进行对比。显示所有仍然打开的句柄。
-disable
(仅用户模式;仅Windows Server 2003和之后的系统) 禁止句柄跟踪。在Windows XP中,只有结束目标进程才能禁用句柄跟踪。

下面开始使用Windbg调试:
1,启动存在内存泄漏的程序后,先使用Windbg附加到该进程上,设置好符号路径:
File -> Attach to a process 附加进程
File -> Symbol File Path 设置PDB符号文件路径

2,输入!htrace –enable开启句柄栈回溯跟踪,该命令同时默认产生第一次句柄信息的快照,后面也可以再输入!htrace –snapshot产生新的句柄初始快照。
在这里插入图片描述

3,F5让程序继续运行,进行会导致句柄泄漏的操作,此时,Windbg会自动中断(或者在Debug菜单下选择Break中断操作), 输入!htrace –diff命令来查看没有删除操作的句柄栈回溯信息,截取其中一个来进行分析:
在这里插入图片描述
4,输入lsa HQIssue!CHQIssueDlg::CreateMemory+0x00000021命令来定位到具体代码:
在这里插入图片描述
再结合具体代码分析,该处内存映射文件句柄确实没有删除,文件选择切换时会导致句柄泄漏。

参考文章:《Windows高级调试》第九章第四节

发布了78 篇原创文章 · 获赞 79 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/bajianxiaofendui/article/details/96353199
今日推荐