句柄泄露调试

2019-07-13 09:05发布

句柄泄露调试(Handles Leak Debug)
一、概述
造成句柄泄露的主要原因,是进程在调用系统文件之后,没有释放已经打开的文件句柄。
对于句柄泄露,轻则影响某个功能模块正常运行,重则导致整个应用程序崩溃。在 Windows系统中, GDI 句柄上限是 12000 个,USER 句柄上限是 18000 个。
与 Windows 系统的设置不同,Linux 系统对进程可以调用的文件句柄数做了限制,在默认情况下,每个进程可以调用的最大句柄数为 1024 个。超过了这个数值,进程则无法获得新的句柄。因此,句柄的泄露将会对进程的功能失效造成极大的隐患。
理论上,我们编程时,1 个进程使用的句柄数建议不应该超过 1000。 二、分析 根据我们项目的测试经验,通常统计出来的句柄图形如下列 3 种:
1、平稳型
这里写图片描述
图 2-1. 平稳图
在程序运行当中,句柄被不断地打开关闭,因此统计图形呈现平稳的锯齿形。在程序运行后期,很多临时打开的句柄被逐渐关闭,总的句柄数量没有随着时间的推移而增加,因此该程序不存在句柄泄露。
2、峰值稳定型
这里写图片描述
图 2-2. 峰值稳定图
在该程序运行初期,程序打开的句柄数量会随着时间的推移而逐步增加。但是当运行一
段时间后,句柄数量会达到一个相对平稳的状态,大概 3500 左右。这个时候表明程序打开
了很多临时句柄,但是句柄数量相对稳定,也不存在句柄泄露问题。
3、递增型
这里写图片描述
图 2-3. 递增图
程序在运行当中,某一操作引起了程序打开句柄数量逐步增加,而且没有出现相对平稳的迹象,说明该程序可能存在句柄泄露,需要进一步分析是哪一部分的句柄存在泄漏,以及什么操作会引起程序句柄的泄露。
通过对程序句柄数量进行采样统计,并且绘制出相应的统计图形,能够以比较直观的方式判断在程序中是否存在句柄泄露。该方法基于程序要运行大量的测试用例,增加测试用例的覆盖率,尽可能多的用测试用例触发程序打开和关闭句柄的操作,这样才能发现潜在的句柄泄露 bug。对于如何能够快速的发现句柄泄露代码,我们将做进一步研究。 三、定位 (WinDBG 调试) 1、运行程序
WinDbg 提供了图形界面和命令行两种运行方式。这里介绍使用图形界面的 WinDbg 来
调试应用程序:
File->OpenExecutable->可以选择一个可执行文件进行调试。
File->Attache to a Process->可以选择一个运行中的进程,并对其进行调试。
这里写图片描述
图 3-1
2、启动句柄操作的栈回溯
按下 F5 快捷键,第 1 次中断进程运行,用!htrace -enable 命令开启句柄检测;htrace 提
供了进行句柄相关检测的命令,可查看 WinDBG 帮助文档。
这里写图片描述
图 3-2
同时用 g 命令让程序运行。
这里写图片描述
图 3-3
3、抓取快照
第 2 次中断进程运行,使用!htrace -snapshot 命令,获得此时进程句柄的镜像。并再次让程序运行。
这里写图片描述
图 3-4 4、运行程序,定位句柄泄露
第 3 次中断进程运行,使用!htrace -diff 命令获得当前句柄状态与第 3 步 snapshot 镜像句柄的差异;
这里写图片描述
图 3-5
通过上面的栈回溯信息,很清楚可以看到句柄打开的地方。使用 lsa 命令可以定位到产
生句柄泄露的方法体代码行,lsa handlew2!fun4+0x0000002e :
这里写图片描述
图 3-6