Panic的小屋

国破山河在,城春草木深。
随笔 - 151, 评论 - 1317, 引用 - 22, 文章 - 0

导航

公告

<2008年10月>
2829301234
567891011
12131415161718
19202122232425
2627282930311
2345678

留言簿(269)

随笔分类

随笔档案

文章档案

相册

国外好站推荐

工具网页

我的其他网页

我的网友

户外运动

美女的空间

搜索

最新评论

阅读排行榜

评论排行榜

GetDC使用中容易忽视的bug

Posted on 2006-07-20 14:10 Panic 阅读(3699) 评论(5)  编辑 收藏

GetDC使用中容易忽视的bug

written by Panic 2006/07/20

msdn中已经有详细说明:

The GetDC function retrieves a common, class, or private DC depending on the class style specified for the specified window. For common DCs, GetDC assigns default attributes to the DC each time it is retrieved. For class and private DCs, GetDC leaves the previously assigned attributes unchanged.

After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. The number of DCs is limited only by available memory.

关键是这一句:

After painting with a common DC, the ReleaseDC function must be called to release the DC.

但是由于GetDC直接返回一个指向CDC的指针(SDK中,返回的是一个HDC句柄),所以可以用这种形式的调用:

GetDC()->XXXXXX

但是这样一来,由于返回值没有保存,就无法进行ReleaseDC的调用了,由此会引起一个GDI资源泄漏。表现就是程序使用的GDI资源数量增加1。

在Win2k下,每个进程的可用GDI资源总数为10000,所以一般情况下这种泄漏不会引起什么实际的问题。但是,当程序需要频繁刷新,或者构造大量GDI对象的时候,就会面临GDI资源耗尽的问题。

GDI资源耗尽,导致的后果是无法创建新的GDI对象,但是在MFC中,GDI对象的构造函数不会因此而抛出异常(因为许多时候,实际的GDI对象不是在构造函数中建立的)。

由于GDI对象创建失败是很罕见的情况,而且失败了,也几乎没什么挽救手段,所以相当多的代码都不检测GDI对象创建是否成功。

以上这些同时存在于一个工程中的时候,就会引起一个难以觉察的bug,他的表现是GDI出现异常显示或者其他错误,直接原因是GDI对象创建失败,本质原因是没有对GetDC得到的返回值做ReleaseDC的调用,导致GDi资源耗尽。

也许其他的Get函数也有类似的问题。

虽然msdn说:The number of DCs is limited only by available memory.但是由于GDI资源总数的限制,这句话并没有实际意义。

我在msdn上没找到GDI对象总数限制的内容,10000个是我在win2kpro sp4上实测的结果。

Feedback

# re: GetDC使用中容易忽视的bug

2006-07-20 14:18 by ksl

# 所以应该用一个类来封装GetDC这样的操作

2006-07-20 16:36 by jzhang
这样在析构函数里可以自动释放.

# re: GetDC使用中容易忽视的bug

2006-08-27 14:02 by 骑猪看夕阳
不错

# re: GetDC使用中容易忽视的bug

2007-04-10 18:11 by 阿赫
实际GDI对象句柄的数目限制是16384个

# re: GetDC使用中容易忽视的bug

2008-10-13 20:30 by littlewater
配对的函数绝对不能够滥用^^
标题  
姓名  
主页
验证码 *
内容   
  登录  使用高级评论  Top
[使用Ctrl+Enter键可以直接提交]