Windows 查找GDI对象泄漏

》原因:

废话不多话,GDI对象泄漏很难找,找了很多方法都没办法方便定位。希望可以帮助需要的人。

》帮助工具:

我们可以通过进程管理器,看到GDI的变化,也可以使用nirsoft的GDIView来看GDI的变化。

》方法:

1. 使用windows API hook机制来实现GDI对象的泄漏定位,已初步测试,能检测到HFONT, HDC, HPEN等对象,其他的没有测试;

2. 花了大半天把Bitmap, Brush, Dc, ExtPen, Font, Palette, Pen, Region等都hook了,可以很方便使用来定位;

3. 由于使用hook之后,程序运行会慢卡,最好是单项对象进行测试分析。

4. 将pdb放在执行目录下,打印出的调用堆栈才能定位到源文件。

5. 源码使用了c++11的一些关键字,请注意编译器版本,测试使用的是vs2013

6. 代码有参考了网上hook的实现,表示感谢。

》示例:

/// 包含头文件
#include "apihook/APIHook.hpp"
#include "apihook/Gdi/Gdi.hpp"

/// 启动堆栈记录
apihook::StackWalker::Inst().Enable();

/// Hook DeleteObject,必须开
apihook::gdi_base::EnableHook();
/// 各个对象使能,自行注释掉不需要的
apihook::gdi_pen::EnableHook();
//apihook::gdi_font::EnableHook();
//apihook::gdi_dc::EnableHook();
//apihook::gdi_bitmap::EnableHook();
//apihook::gdi_brush::EnableHook();
//apihook::gdi_extpen::EnableHook();
//apihook::gdi_palette::EnableHook();
//apihook::gdi_region::EnableHook();
/// 运行一段时间后,或者操作某个界面后,打印泄漏信息到执行目录下
/// 打印需要通过DeleteObject释放的泄漏地址
apihook::gdi_base::MyStacks_base::Inst().Dump("gdi.leak");
/// 打印需要通过ReleaseDC释放的泄漏地址,需要开启gdi_dc
//apihook::gdi_dc::MyStacks_relasedc::Inst().Dump("releasedc.leak");
/// 打印需要通过DeleteDC释放的泄漏地址,需要开启gdi_dc
//apihook::gdi_dc::MyStacks_deletedc::Inst().Dump("deletedc.leak");

/// 禁用各个对象Hook
apihook::gdi_base::EnableHook();
apihook::gdi_pen::DisableHook();
//apihook::gdi_dc::DisableHook();
//apihook::gdi_font::DisableHook();
//apihook::gdi_bitmap::DisableHook();
//apihook::gdi_brush::DisableHook();
//apihook::gdi_extpen::DisableHook();
//apihook::gdi_palette::DisableHook();
//apihook::gdi_region::DisableHook();

// 关闭堆栈打印
apihook::StackWalker::Inst().Disable();


可以随便在你的代码里面加入

HPEN hpen = ::CreatePen(PS_SOLID, 2, RGB(255, 0, 0));
CDC* pDC = GetDC();
等不释放的做测试。

》源码:

哈哈,关键是源码,请从github上下载,地址是:https://github.com/henly2/pink/tree/master/source/apihook




你可能感兴趣的:(Windows,debug,VC)