WinDbg 定位句柄泄漏问题

一、观察进程是否有句柄泄漏

1、查看工具

使用任务管理器或Process Explorer(procexp.exe)工具可观察进程的句柄数。

任务管理器查看句柄数

查看句柄数

procexp.exe查看进程句柄信息

查看句柄

2、判断是否有句柄泄漏

通常在程序运行稳定后,再观察句柄数有无增长,比如进程启动5分钟后再开始观察,让其运行半天或一天,比较前后的句柄数有无明显增长。
可以使用性能监视工具或者在Procexp.exe选中进程,点击菜单中的保存可以存成txt文本查看,可以通过比较前后两次的txt查看哪些句柄有泄漏。

二、定位方法

1、WinDbg分析句柄泄漏

1.1 Event句柄泄漏
1.1.1 代码示例
#include "stdafx.h"
#include <ctime>

void HandleLeak()
{
	for (int i = 0; ; i++)
	{
		CreateEvent(NULL, true, false, NULL);
		Sleep(10000);
	}
}


int _tmain(int argc, _TCHAR* argv[])
{
	HandleLeak();
	
	system("pause");
	return 0;
}

生成文件名为testC.exe

1.1.2

1)打开WinDbg,设置好pdb路径以及源码路径
设置路径
2)打开exe
打开进程
进程
3)在WinDbg命令窗口中执行g
g
回车换行,进程启动了
进程启动
4)过一会后,点击WinDbg菜单栏的Break或者按下Ctrl+Break
break
5)此时分别执行以下命令
!htrace -enable:启用handle trace,并且创建第一个快照作为初始状态,方便使用 -diff选项
!htrace:显示当前的所有句柄信息
!htrace -snapshot:创建快照,用作-diff选项
执行命令
执行一下g命令,同3)

6)过一会后,break掉,同4),在WinDbg命令窗口执行
!htrace -diff:使用当前状态的信息,和最近一次的快照信息做对比
diff
handle
由图可知,和快照做对比,发现比快照多了7个handle

7)根据6)中的handle值,执行
!handle xxx f:查看一下handle的信息
handle
handle内容
从这里可以知道这个handle的类型是event

8)在有源码和pdb的情况下,可以使用 lsa命令定位到源码所在位置,如

lsa KERNELBASE!CreateEventExW+0x0000000000000056

当然这里因为是windows内部的模块,没有加pdb和源码,因此不会显示到对应行

9)根据7),我们看不见是我们那一行代码导致的问题,因此可以反汇编获取函数的返回地址,如下:
ret

我们找到返回地址,图中箭头位置,拿到7713a02a

10)调试一下断点
调试

.logappend /u e:/test.log:表示将此命令的结果Append到e:/test.log文件中,/u表示 in Unicode format。
k :表示输出栈信息
r eax:表示输出eax寄存器的值,即取函数的返回值
.logclose:表示关闭日志记录                             
g:表示命中断点后继续执行

11)打开test.log
日志

由日志去查看源代码,发现CreateEvent后没有close的操作,到此就定位出了Event句柄泄漏的位置。

备注:当我们从文件得知可能出现句柄泄漏的句柄时,我们可以用windbg挂对应的进程,等对应的进程或目录或其他名称出现,这个时候用procexp看对应句柄值,再在windbg执行!htrace -diff的内容中查找对应的句柄值。

  • 1
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值