关于操作DC时的资源泄露

首先应明确一个概念 句柄, 关于句柄的详细介绍请见这里

对于句柄的使用小结:借来的要归还,创建的要释放,选出的要选入【尤其是针对GDI的一些句柄而言,如HPEN,HBRUSH等】

1. 使用GetDC() 获取的设备上下文指针在不使用的时候必须调用ReleaseDC()进行释放

例如:

1 CDC *pDC = GetDlgItem(IDC_TEST)->GetDC();
2
3 /*...............*/
4
5 GetDlgItem(IDC_TEST)->ReleaseDC(pDC);

2. 在创建了DC或其他GDI资源后,如果不再使用则需要将所创建的资源进行释放

例如:

1 CDC dcMem;
2
3 dcMem.CreateCompatibleDC(NULL);
4
5 /*..............*/
6
7 dcMem.DeleteDC();

3. 在将创建的GDI绘图对象选入了设备上下文后,如果使用完毕则需要将之前选出的旧有的GDI绘图对象选入,然后在删除所创建的GDI对象

例如:

 1 CBitmap bmp;
 2
 3 bmp.CreateCompatibleBitmap(pDC, nWidht, nHeight);
 4
 5 CBitmap *pBmpOld = memDC.SelectObject(&bmp);
 6
 7 /*..................................*/
 8
 9 memDC.SelectObject(pBmpOld);
10
11 bmp.DeleteObject();

说明:一定要注意SelectObject的操作通常要成对出现,否则可能会导致GDI资源泄露。例如上面的例子,如果在最后我们没有执行语句

memDC.SelectObject(pBmpOld);只是调用了bmp.DeleteObject(),此时对于bmp资源的释放是失败的,即无法将之前所创建的位图图像删除。

Attach 的需要Detach

例如:

 1 CImage img;
 2
 3 if (SUCCEEDED(img.Load(strFileName)))
 4
 5 {
 6
 7   HBITMAP hBitmap = img.Detach();
 8
 9   /*......................*/
10
11   img.Attach(hBitmap);
12
13 }
14
15 img.Destroy();

1. 被选入的绘图对象(如:bitmap、brush等)无法删除,只有当调用SelectObject将对象选出后才可以删除

2. 对于SelectObject()成对出现的原因?

例如:

1 bitmap = CreateCompatibleBitmap(...);
2 HBITMAP oldbitmap = SelectObject(hdc, bitmap);
3 ...
4 SelectObject(hdc, oldbitmap);
5 DeleteObject(&bitmap) 

注意:

1. SelectObject必须成对存在

2. 对于上面代码段的第四行,调用SelectObject将oldbitmap选入之后不需要将返回值再赋给bitmap,此时bitmap已经是最新的位图对象了(哪怕在语句3对选入的位图进行了操作)

3. 对于GDI绘图资源的释放一定要注意,一旦有资源没有得到释放,而且执行的频率又非常频繁的情况下,就很容易导致资源无法创建的问题。尤其是在OnCtlColor中一定不要创建画刷等绘图对象,而是应该将需要用到的绘图对象定义为类的成员变量。

4. 由于对于GDI而言,windows只使用了16位字段来指明句柄,因此所能创建的GDI句柄总数应不大于64K个,实际上受其他一些限制,整个windwos系统中大概可以容纳约16384(0x4000)个GDI对象。一旦超过这个总数,就会使得Windows抛出ResourceException

时间: 2024-12-15 07:08:54

关于操作DC时的资源泄露的相关文章

如何检测资源泄露

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

Struts2中使用Velocity模板时模板资源路径配置问题

在Struts2中使用Velocity模板时,如何以相对与Web工程的路径来配置模板资源文件路径这个问题网上千篇一律的来自Velocity官方文档.官方文档中指出如果是Web工程的话,模板的相对路径是工程根路径,今天在使用的时候有如下配置: Velocity.properties(默认在WEB-INF下): resource.loader =file, classclass.resource.loader.description = Velocity Classpath Resource Loa

LTE物理传输资源(3)-时频资源

在博文<LTE物理传输资源(1)-帧结构和OFDM符号>里提到了LTE的帧结构和时域上的OFDM符号,本文继续这个话题,继续描述子帧和时隙结构里的其他内容. 1.资源粒度 为提高终端的功率效率,延长电池的续航时间,以及设备成本上的考虑,LTE上行链路采用SC-FDMA(Single Carrier Frequency Division Multiple Access,单载波频分多址)技术.在时域上,最小的资源粒度是一个OFDM符号(上行是SC-FDMA符号.下文统一称为OFDM符号).在频域上

避免资源泄露的一个方法

1.一个资源,很多人用,如果大家都不delete,必定造成资源泄露 2.如果多个人进行delete,必定导致未定义行为. 3.因此,只能有一个delete,而且必须是最后一个使用者进行delete. 4.那么问题来了,我怎么知道谁是最后一个使用者?在多线程的环境中更加不可能判断出来.那怎么办呢? 5.不要想着谁是最后一个使用者,换个角度,每个使用者使用前都进行addRef,使用后都进行release,这样就保证了最后一个使用才进行delete. 避免资源泄露的一个方法,布布扣,bubuko.co

C#操作word时出现的office错误

每次运行WORD都会出现一个提示窗口--"此错误通常是由宏安全性设置造成的.如果您知道宏来自您信任的来源,则可将宏安全性设置更改为允许启用宏.宏安全性设置的更改方式取决于您使用的Microsoft Office System 程序." Word2007提示错误"此错误通常是由宏安全性设置造成"的解决方法有以下几种: 方法一: Word选项--加载项--管理[com加载项],转到--把几个勾勾都取消掉--确定,即可.Win7中注意要以管理员身份进行,因为这些写入了注册

c#操作ecxel的一些资源(downmoon搜集)

c#操作ecxel的一些资源(downmoon搜集) 工作需要,邀月收集了几个操作excel的资源.  1.如何:使用 COM Interop 创建 Excel 电子表格(C# 编程指南)http://msdn.microsoft.com/zh-cn/library/ms173186(VS.80).aspx 2.从 .NET 开发人员的角度理解 Excel 对象模型http://msdn.microsoft.com/zh-cn/library/aa168292(office.11).aspx 3

Spring AOP操作action时无法注入,报NullPointer异常

Spring AOP操作action时无法注入,报NullPointer异常当使用Spring AOP对action层进行操作时,会出现注入失败的问题,出现空指针异常.原因是一般struts2+spring应用中,spring的插件只负责为action的ioc部分,但并没有进行功能加强,即采用代理的机制,所有的action还是使用struts2进行管理,在使用AOP后,这些action需要由spring进行管理,如果没有由spring进行代理,将出现注入失败.解决办法:Struts2的一个特殊的

有时候在操作Session时,系统会抛出如下异常:java.lang.IllegalStateException: Cannot create a session after the response has been committed

有时候在操作Session时,系统会抛出如下异常 java.lang.IllegalStateException: Cannot create a session after the response has been committed 原因1: Session 的创建语句: HttpSession seesion = request.getSession(); 之前有Response的输出语句. 应该把HttpSession seesion = request.getSession(); 放

C#操作Excel时的格式设定(转)

Excel报表打印的格式设定 1.     表头的设置 Excel._Worksheet myWorksheet; myWorksheet.PageSetup.Orientation = Excel.XlPageOrientation.xlLandscape; //纸张方向, 返回或者设置对象的方向, 纵向或横向打印模式 //Excel.XlPageOrientation.xlLandscape   landscape mode  :worksheet横幅 //Excel.XlPageOrien