-
-
[求助]软件调试基础--10搞定句柄泄露
-
发表于: 2016-1-27 15:16 4980
-
相比内存泄露,句柄泄露的发生情况还算少数,其实句柄也是一个很有限的资源,而且句柄几乎都关联了一段内存,所以大多数情况下,有句柄泄露的地方其实也是有内存泄露的,任务管理器里可以查看到某进程中的句柄数量,如果我们的程序运行过程中,发现句柄数量在稳增不减,那基本上就说明这个程序有句柄泄露了,当程序执行时间足够长,就会导致崩溃,或创建新的句柄失败。本文讲解,如何查找泄露的句柄,在创建这个句柄的时候的调用堆栈,有了调用堆栈,我们就可以找到这个句柄是否有释放过,如果没有,我们就可以在合适的时机对其进行释放了。
原理:思路跟找内存泄露基本一样,也是捕获两个时间点时程序中的句柄,然后对比两个时间点里不同的句柄,并打印出这些句柄的创建时的调用堆栈。
下面以一个最简单的例子,来演示一下。主要代码如下:
void CMFCTestDlg::OnBnClickedOk()
{
// TODO: 在此添加控件通知处理程序代码
HANDLE hEvent = CreateEvent(NULL, TRUE, TRUE, NULL);
}
点击一下按钮的时候,创建了一个事件对象,并且没有CloseHandle。本文实验环境为XP系统,Win7下由于Windbg版本较低,有些内容显示不正常。
Windbg启动调试,并开启句柄监视,其实就是把句柄创建的调用堆栈存储起来,同样是之前讲解的用户态栈回溯数据库。(看吧,很多表面上的问题,其实底层原理都一样的)如下图:
然后创建一个句柄快照,如下图:
继续执行,点击按钮,创建一个Event,然后ctrl + break中断下来,执行对比,如下图:
这里可能显示很多个调用堆栈,但不一定每一个句柄都是泄露,和前面内存泄露一样,两次对比产生的差异未必都是泄露,有一部分系统本身的,只是我们第二个时间点之前还没有释放,而之后是有释放的。
总结:本篇内容比较少,其实就是几个命令而已,很简单,重点是知道原理,windows为我们开发者提供了哪些支持,适当的时候要学会利用这些支持解决问题。