告诉你GetDC()没有释放造成的后果

最近做的项目中需要显示视频监控窗口,从采集卡中读到图像的数据,需要实时显示出来,而且速度比较快。

由于比较简单,就直接使用了GDI画图,以前复杂的都用openGL啥的工具了,这次这个简单,就直接用GDI了。

先获取DC,然后画图

    pDC = this ->GetDC();        // 获得显示控件的 DC
    this->GetClientRect(rect);
    MemDC.CreateCompatibleDC(NULL);
    //这时还不能绘图,因为没有地方画 ^_^
    //下面建立一个与屏幕显示兼容的位图,至于位图的大小嘛,可以用窗口的大小
    MemBitmap.CreateCompatibleBitmap(pDC,640,480);
    pentemplate.CreatePen(PS_SOLID,1,RGB(0,255,255));
    penkuang.CreatePen(PS_SOLID,1,RGB(255,0,255));
    MemDC.SelectObject(&MemBitmap);
    //printf("\n 拷贝图片");
    StretchDIBits(MemDC.m_hDC,                                // 设备环境句柄
        0,                 //目标X坐标
        0,                  // 目标Y坐标
        640,            // 目标宽度
        480,           // 目标高度
        0,                // 源X坐标
        0,                 // 源Y坐标
        640,           // 源宽度
        480,          // 源高度
        ImageBuff,                //图像数据指针BYTE*
        &bmpInfo,         // 指向位图信息结构的指针
        DIB_RGB_COLORS,                 // 使用的颜色数目
        SRCCOPY); 

结束后进行释放内存DC和创建的画笔对象

    pDC->BitBlt(0,0,640,480,&MemDC,0,0,SRCCOPY);
    //printf("画图结束\n");

    MemBitmap.DeleteObject();
    penkuang.DeleteObject();
    pentemplate.DeleteObject();
    MemDC.DeleteDC(); 

注意,此时只对创建的内存DC和画笔对象进行了释放,对获取的pDC没有释放,这样短时间没什么问题,但是程序跑了几分钟以后,界面就没有反映了,整个界面卡死了,完全动不了。

这个问题困扰了我好几天,试了各种方法无果。

后来请教了一个朋友,朋友看到代码后,说pDC没有释放,我说GetDC需要释放吗,又不是new的。他说需要释放。

于是添加了

ReleaseDC(pDC);

重新跑下程序,跑了一天一也没有死。

但是问什么不释放会使程序界面卡死呢?于是对释放和不释放两个版本的程序进行观察。

启动任务管理器,把GDI对象添加到进程列中,观察两个版本的程序运行情况。程序名为OnlineFast

使用释放的版本,可以看到GDI对象保持157不变。

如果没有释放的话,GDI对象会一直增加

当然,此时程序还没有死,但运行一段时间后,当GDI对象增加到10000的时候,程序就死了,这就是GDI对象的极限了。

所以,GetDC 和ReleaseDC一定要配对使用,获取了,没有去释放,windows不会自动去释放,一直占用这,直到到达极限,资源耗尽,程序就崩溃了。

照例贴上俩儿子的照片,又离家一个月了,一个月没见到俩儿子了。

时间: 2024-08-14 01:15:20

告诉你GetDC()没有释放造成的后果的相关文章

使用new来创建动态数组

原文来自:http://book.51cto.com/art/201211/367161.htm 使用new来创建动态数组(1) 如果程序只需要一个值,则可能会声明一个简单变量,因为对于管理一个小型数据对象来说,这样做比使用new和指针更简单,尽管给人留下的印象不那么深刻.通常,对于大型数据(如数组.字符串和结构),应使用new,这正是new的用武之地.例如,假设要编写一个程序,它是否需要数组取决于运行时用户提供的信息.如果通过声明来创建数组,则在程序被编译时将为它分配内存空间.不管程序最终是否

对 block 内存管理的一些看法

首先交代一下retain cycle ,和 产生retain cycle后我们应该怎么处理. 1.retain cycle在block中是极易产生,block就是一段可以灵活使用的代码,你可以把它当做变量传递,赋值,甚至可以把它声明到函数体中.更加灵活的是它可以引用它的承载着(即就是block的运行环境),但是这样子就更容易产生retain cycle了 .就是简单说类比 子控件拥有父控件的引用,而父控件也拥有子控件的引用.这样相互引用.就不能形成父控件释放也能将子控件释放.这就造成一个内存泄露

VC++学习之多线程(2)

创建一个线程,自然有一个相应的系统API来完成.CreateThread这个函数就用来创建线程的. 各种参数的用途我就不多说了,这里直接贴一个我自己练习的例子 1.下面是一个创建一个线程的例子,当然,仅仅是创建: #include<windows.h> #include<iostream> using namespace std; DWORD WINAPI Fun1Pro(LPVOID laparameter); int main() { HANDLE hthread1; hthr

关于内存泄露

1.new,malloc后没有delete,free 这些内存在Debug时候都可以Dump出信息的 2.创建内核对象(比如CreateFile,CreateMutex,CreateThread),后没有释放内核对象句柄. 3.创建内存映射文件,CreateFileMapping,MapViewOfFile后没有CloseHandle(),UnMapviewofFile 4.创建GDI对象后,比如LoadIcon,LoadImage,CreateImageList等等,没有Destroy掉 5.

[ERP]ERP实施天下无贼版

自牛群和冯巩在某年春晚上开起了<小偷公司>,虽然在声势上狠狠地火了一把,但经营不佳,不得不更换了新的CEO,由一个江湖大偷--号称"黎叔"掌管.这位黎叔在2005贺岁之际,做出惊人之举:小偷公司也要实施ERP!以下记录了此事的一些情景和对话,颇似电影<天下无贼>,我们都怀疑他们在抄袭. 作为倡导者黎叔的认识和态度是非常鲜明的. 实施伊始,他在为大家鼓劲时总是爱说:这次出来(ERP项目)一是锻炼队伍,二是考察新人,在这里我特别表扬两个同志,"肯干的&qu

IOS 多个UIImageView 加载高清大图时内存管理

当我们在某一个View  多个UIImageView,且UIImageView都显示的是高清大图,就有可能出现内存警告的问题.如果第一次进入这个view,没有发生内存警告,当再次进入这个view,如果上一次的内存没有及时释放,这一次次的累加,便可导致内存崩溃. 1,UIImage 加载图片的方式.      如果是本地图片,尽量不要使用 [UIImage  imageNamed:nil]; 这种方式,如果使用这种方式加载,只要程序不退出,它便一直会在内存中.     我们可以使用 :      

Android APP性能分析方法及工具

近期读到<Speed up your app>一文.这是一篇关于Android APP性能分析.优化的文章.在这篇文章中,作者介绍他的APP分析优化规则.使用的工具和方法.我觉得值得大家借鉴.英文好的读者可读原文(链接:http://blog.udinic.com/2015/09/15/speed-up-your-app). 1.作者的规则 作者每次着手处理或寻找性能问题时,遵循下列规则: 时常检测 在更新APP前后,用测试工具软件多检测几次APP性能,可快速得到测试数据.这些数字是不会说谎的

OSChina 周三乱弹 —— 前所未有的空虚

各位OSCer 大家壕,周三了,熬过今天,就可以放假,你不上班的时候会空虚吗,会寂寞吗? @在湖闻樟:最近有点空虚,还是把一直很想翻译的Supporting Python 3翻译下吧 然而,最近瑞典的这位泊松老兄,也说自己感到空虚了,原因是钱太多 @喵小强:程序猿一夜暴富坐拥百亿:前所未有的空虚....空虚..虚 以下是泊松的推文,随便发几句牢骚就可以让世界津津乐道,大家可以感受下 泊松的经历告诉我们,太有钱导致的后果:1.追不到妹子:2.被人讨厌:3.没人陪你玩 看来有钱真是太可怕了,以后再也

指针和自由存储空间

指针是一个变量,其存储的是值的地址,而不是值本身. 对变量应用地址运算符(&),就可以获得它的位置. 使用常规变量时,值是指定的量,而地址为派生量.下面来看看指针策略,它是C++内存管理编程理念的核心. 指针与C++基本原理 面向对象编程与传统的过程性编程的区别在于,OPP强调的是在运行阶段(而不是编译阶段)进行决策.运行阶段指的是程序正在运行时,编译阶段指的是编译器将程序组合起来时. 运行阶段决策提供了灵活性,可以根据当时的情况进行调整.在运行阶段做决策并非OPP独有的,但使用C++编写这样的