首页 > 代码库 > 如何检测资源泄露

如何检测资源泄露

Window上我们常见的资源泄露包括内存和对象句柄泄露, 下面讨论下对各类泄露的检测方法。
关于内存泄漏,我以前写过2篇文章: C++中基于Crt的内存泄漏检测, 基于WinDbg的内存泄漏分析
用上面提到的方法检测泄露很多时候太麻烦,所以有时候我们会考虑用工具 VLD:

Visual Leak Detector源于Code ProjectVisual Leak Detector - Enhanced Memory Leak Detection for Visual C++安装包可以到 这里 下载。

使用很简单,基本上安装完了就之可以直接用, 具体可以参考 这篇


关于对象句柄泄露, 主要分GDI对象,Kernel对象,User对象:

GDI对象只在本进程有效,主要是指Brush, Pen,DC等, 具体可以参考 这里

User对象只在同一Session内有效,同一user对象在不同进程内值都相等,可以跨进程使用, 主要是指Menu, window, cursor, hook等,具体可以参考 这里

Kernel对象可以跨进程使用, 但是因为每个进程都有自己的内核对象表,所以同一对象的句柄值在不同进程里会不相等(尽管最终指向同一个内核对象),主要是指各类HANDLE,具体可以参考 这里


对于对象句柄泄露,免费来说没有太好的工具可以直接使用, 很多时候我们可以直接通过任务管理器来观察各类对象的个数, 如果有持续增长, 则说明有泄露存在。很多时候GDI泄露是大头,我们要判断哪类GDI对象正在泄露,可以考虑使用工具GDIView。(对于对象句柄泄露,谁有好的工具,可以提示下。)


对于内核对象泄露,我们可以考虑使用WinDbg的 !htrace 命令, 使用很简单:通过 !htrace -enable 命令打开栈回溯, 然后通过 !htrace -snapshot 命令保存一个当前所有句柄的快照, 最后再通过 -htrace -diff 命令获取所有前面保存快照后打开但没有关闭的句柄对象。


如果公司有钱,可以考虑购买Boudcheck, 这个工具非常强大,可以帮我们快速的检测出各类内存和对象泄露,包括API的参数错误等。思考Boundcheck的实现原理,实际上并不复杂,主要就是API Hook, 大概过程如下:

(1) 将注入对方进程

(2) 通过API Hook替代系统资源分配和释放相关的API, 并且记录调用栈

(3)最后检测没有释放的资源, 生成报表


这里有篇文章告诉你如何开发类似的工具:LeakMon - Track Handle leak, GDI Leak and Memory Leak in your Applications

当然尽管原理很简单,但是因为Windows的API种类繁多,并且在新版本中会常有增加, 要开发一个完整的工具也不是一件容易的事情。

如何检测资源泄露