额.. 又漏了…

这次是GDI+ 的调用引起的, 看代码吧:

主要问题在于Graphics 那个对象. 实际上当前代码的SelectObject() 调用是错误的, 结果就是HBITMAP 对象又泄漏了. 解决的办法就是Graphics 对象用完了就删掉, 就不会锁住里面的HBITMAP 对象了. 方法有2 种: 1) 加一个作用域, 就是把上面的注释去掉. 2) new 一个Graphics 对象, 用完了直接delete 掉.

发现GDI+ 虽然封装了一些比较好用的函数, 但是很容易出错, 而且performance 也不太好. 以后还是少用为妙.

第一篇技术文…

内存泄漏, 句柄泄漏.. windows 编程中最头痛的事情. windows 提供了查看内存检测内存泄漏的API, 却没有提供检测句柄的, 至少我不知道. 第三方的工具如BoundsChecker 倒是异常强大.实在不行并且看得懂nc 堆栈信息的话, 可以用用看M$自家的 AppVerifier .

今天碰到的问题很诡异. 在用工具检查完GDI 句柄泄漏之后, 跑了一上午某个绘图程序, 内存居然涨到了100+M, ft 啊. 于是代码一段段注掉, 找到底哪里漏了… 最后定位到这样的一段代码:

问题在于, 最后的DeleteObject() 调用不正确. 应改为如下:

就是说, 一个HBITMAP 跟一个HDC 还有关联的时候, 不要调用DeleteObject(), 而应该先把原始的HBITMAP 句柄SelectObject() 还原回去. 有以下几条notes:

  • Bitmaps must be disconnected from a DC before being freed.
  • Menus must be freed before an application exits if the menu is not connected to any window.
  • A DC must be disconnected from bitmaps before being freed.
  • If a bitmap is specified for the Caret, it must be freed.
  • Calls to DeleteObject do not harm stock objects.