牵着老婆满街逛

严以律己,宽以待人. 三思而后行.
GMail/GTalk: yanglinbo#google.com;
MSN/Email: tx7do#yahoo.com.cn;
QQ: 3 0 3 3 9 6 9 2 0 .

利用任务管理器侦测GDI内存泄露

转载自:http://zhanyonhu.blog.163.com/blog/static/1618604420100232033650/


        打开任务管理器,点击菜单“查看”——“选择列”,勾上所有项,“确定”。运行自己的程序,进行各种操作,并查看任务管理器中GDI对象和句柄数的变化。

        如果在某次可逆操作中,例如,弹出一个对话框,然后关闭,GDI对象或句柄数先增加了,然后减少了,但是总量还是增加了,说明存在内存泄露,GDI对象没有被及时回收。如果句柄数出现类似情况,则情况复杂很多。

        接下来,注释掉某些代码,编译运行并继续观察,逐步定位导致内存泄露的代码段。

 

        实例:

        某程序运行时,弹出一个窗口,再关闭,GDI对象数目就增加了一个。经过一个多小时的分析,最后定位出问题所在,如下:

 LOGFONT logfont={0};

 GetObject(m_font, 
sizeof(logfont), &logfont);

 logfont.lfHeight 
= -MulDiv(size, GetDeviceCaps(::GetDC(NULL), LOGPIXELSY), 72);

 SetFont(
&logfont);

        这段代码是用来改变窗口的字体大小的,size是字体的磅数,但是LOGFONT是按像素计算字体大小的,所以,需要转换字体的磅数为像素大小。这里只转换了高度,因为设置字体大小时,只需要高度就可以了。 logfont.lfHeight = -MulDiv(size, GetDeviceCaps(::GetDC(NULL), LOGPIXELSY), 72);  这句代码是从网上搜索到的、转换字体磅数为像素大小的代码,我也没有去细看,直接copy了一下,毕竟代码很短,乍一看,真没什么问题。然而,这里使用了GetDC,这将导致GDI对象增加,所以,应该调用DeleteDC回收,这就是问题所在。

修改后的代码为:


 LOGFONT logfont={0};

 GetObject(m_font, 
sizeof(logfont), &logfont);

 HDC hdc
=::GetDC(NULL);

 ASSERT(hdc
!=NULL);

 logfont.lfHeight 
= -MulDiv(size, GetDeviceCaps(hdc, LOGPIXELSY), 72);

 ::DeleteDC(hdc);

 SetFont(
&logfont);

By:zhanyonhu

posted on 2011-03-09 17:26 杨粼波 阅读(1598) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理