DrawImage导致内存疯长,求解决方法

hcl545 2012-04-23 11:45:33
各位兄台:
求助!!本人开发一个程序,需要用到ImageDraw显示,但遇到问题,当连续显示多付图像的时候,会出现内存疯狂增加的情况,自己琢磨很久也不得其解,请帮助一下,非常感谢!代码如下:
CRect rect;
pictureConIDCam1-> GetClientRect(rect);
CDC *pDC = pictureConIDCam1-> GetDC( );
CBitmap bitmap;
bitmap.CreateCompatibleBitmap( pDC, rect.Width( ), rect.Height( ) ); //创建内存位图时只需要和显示窗体客户区大小相同,创建的大了也是没用的!!!。
CDC memDC;
memDC.CreateCompatibleDC( pDC );
CBitmap *pOld = memDC.SelectObject( &bitmap );
memDC.SetStretchBltMode( COLORONCOLOR );

Graphics graphics( memDC );
graphics.SetInterpolationMode(InterpolationModeLowQuality);
HGLOBAL hGloabl = GlobalAlloc(GMEM_MOVEABLE,ImageBufferStructCam-> lengthall);

if (hGloabl == NULL)
{
return 0;
}
void *pData = GlobalLock(hGloabl);
memcpy(pData,ImageBufferStructCam-> bufImageAll,ImageBufferStructCam-> lengthall); //ImageBufferStructCam是我定义的结构体,返回图像的长度及内存地址;

IStream* pStream = NULL;
if (CreateStreamOnHGlobal(hGloabl,true, &pStream) != S_OK)
{
GlobalFree(hGloabl);
delete ImageBufferStructCam-> bufImageAll;
delete ImageBufferStructCam;
return 0;
}
if (pStream == NULL)
{
GlobalFree(hGloabl);
delete ImageBufferStructCam-> bufImageAll;
delete ImageBufferStructCam;
return 0;
}

Image image( pStream );

graphics.DrawImage( &image, 0, 0, rect.Width( ), rect.Height( ) ); //图像缩放到窗体大小
pDC-> BitBlt( 0, 0, rect.right, rect.bottom, &memDC, 0, 0, SRCCOPY );
//由于搞不清楚哪些资源没有被释放,我把能想到的全加上了,但依然内存泄露厉害。
memDC.SelectObject(pOld);
bitmap.DeleteObject();
memDC.DeleteDC();
graphics.Clear(0);//
GlobalUnlock(hGloabl);
GlobalFree(hGloabl);
// graphics.~Graphics();
// Graphics.ReleaseHDC()
delete ImageBufferStructCam-> bufImageAll;
delete ImageBufferStructCam;
return 0;

说明:由于要连续显示很多图像(30帧/s),使得图像像录像一样显示出来,因而上述代码会反复执行。我追踪了一下,发现出现内存泄露的地方集中在graphics.DrawImage( &image, 0, 0, rect.Width( ), rect.Height( ) ); 这条语句,前面的代码与后面的都不会出现该泄露。不知道怎么回事,怎么释放了!怀疑windows 7释放内存速度太慢,系统反应不过来,但又苦于找不到vc下的内存强制释放代码!!!请帮助。非常感谢
...全文
906 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
hcl545 2012-04-26
  • 打赏
  • 举报
回复
问题解决了一半,无语,结贴
向立天 2012-04-24
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 的回复:]

引用 17 楼 的回复:

看来确实和DrawImage有关
不过很难解释是为什么
看样子原因也许在这里:我追踪了一下,发现DrawImage耗时需要近100ms(有时大于有时小于100ms),也许是因为前面内存还没释放,后面又开始申请内存,30帧/s的显示速度下,同时在内存中的数据将达到五个,也就是说:旧的还没释放,新的又申请了,这导致内存释放能力下降,最终导致数据无法释放,而出……
[/Quote]
如果是这样的话就换一种现实方式吧
hcl545 2012-04-24
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 的回复:]

看来确实和DrawImage有关
不过很难解释是为什么
[/Quote] 看样子原因也许在这里:我追踪了一下,发现DrawImage耗时需要近100ms(有时大于有时小于100ms),也许是因为前面内存还没释放,后面又开始申请内存,30帧/s的显示速度下,同时在内存中的数据将达到五个,也就是说:旧的还没释放,新的又申请了,这导致内存释放能力下降,最终导致数据无法释放,而出现泄漏
hcl545 2012-04-24
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 的回复:]

引用 20 楼 的回复:

[/Quote]
呵呵,你的乐观精神,值得咱我好好学习!致敬!!
向立天 2012-04-24
  • 打赏
  • 举报
回复
[Quote=引用 20 楼 的回复:]

引用 19 楼 的回复:

引用 18 楼 的回复:

确实如此:考虑换directDraw实现,gdi与gdi+都不行,就只能换了!!哎,初次正儿八经用vc开发项目,就遇到这么多问题,难啊!!!!
[/Quote]
其实用VC开发的乐趣也就在这里
hcl545 2012-04-24
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 的回复:]

引用 18 楼 的回复:
[/Quote]
确实如此:考虑换directDraw实现,gdi与gdi+都不行,就只能换了!!哎,初次正儿八经用vc开发项目,就遇到这么多问题,难啊!!!!
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
建议,不要把GlobalLock这类的图像加载代码放到OnPaint或DrawItem等绘制函数里,放在外部的一个自己定义的函数,在PruSublcassWindow等初始化函数中调用自定义的函数,来完成图像加载的工作,在析构函数等程序结束的函数中来执行GlobalUnlock类的卸载图像的函数。
[/Quote]
谢谢,zhllxt,主要是因为我需要反复显示同分辨率,但大小不同的JPEG图像,因而,我只能建立一个timer,在timer中每次运行上述程序,加载不同的图像进行显示。
zhllxt 2012-04-23
  • 打赏
  • 举报
回复
建议,不要把GlobalLock这类的图像加载代码放到OnPaint或DrawItem等绘制函数里,放在外部的一个自己定义的函数,在PruSublcassWindow等初始化函数中调用自定义的函数,来完成图像加载的工作,在析构函数等程序结束的函数中来执行GlobalUnlock类的卸载图像的函数。
向立天 2012-04-23
  • 打赏
  • 举报
回复
看来确实和DrawImage有关
不过很难解释是为什么
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 的回复:]
你说DrawImage本身会导致内存泄露这个不太可能
不过我倒是怀疑由于image是由pStream初始化的
所以DrawImage导致pStream的泄露
建议你在这个位置通过其他方式(比如文件)加载image测试一下是否泄露
而且还是建议image的构造不要放到OnPaint中
[/Quote]
谢谢xianglitian,我已经进行过测试,代码如下:


CRect rect;
pictureConIDCam1->GetClientRect(rect);
CDC *pDC = pictureConIDCam1->GetDC( );
CBitmap bitmap;
bitmap.CreateCompatibleBitmap( pDC, rect.Width( ), rect.Height( ) );
CDC memDC;
memDC.CreateCompatibleDC( pDC );
CBitmap *pOld = memDC.SelectObject( &bitmap );
memDC.SetStretchBltMode( COLORONCOLOR );

Graphics graphi( memDC );
Image *image;
static int i =0;
if (i==0)
{
image = Image::FromFile( _T("E:\\1.JPG") ); /*pStream*/
i=1;
}
else
{
image = Image::FromFile( _T("E:\\2.JPG") ); /*pStream*/
i=0;
}


graphi.DrawImage( image, 100, 100, rect.Width( ), rect.Height( ) ); //图像缩放到窗体大小
pDC->BitBlt( 0, 0, rect.right, rect.bottom, &memDC, 0, 0, SRCCOPY );

delete image;
pictureConIDCam1->ReleaseDC(pDC);
memDC.SelectObject(pOld);
memDC.DeleteDC();
bitmap.DeleteObject();

我将该代码放置于timer中,循环加载2副JPG图像,当30帧/s时,同样会出现内存增加的情况,而当10帧/s时,则不会出现上述问题。谢谢!!
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 的回复:]
CDC *pDC = pictureConIDCam1-> GetDC( );

需要ReleaseDC
[/Quote]
谢谢!添加该控件的释放后,问题依旧,代码见8楼
向立天 2012-04-23
  • 打赏
  • 举报
回复
你说DrawImage本身会导致内存泄露这个不太可能
不过我倒是怀疑由于image是由pStream初始化的
所以DrawImage导致pStream的泄露
建议你在这个位置通过其他方式(比如文件)加载image测试一下是否泄露
而且还是建议image的构造不要放到OnPaint中
  • 打赏
  • 举报
回复
CDC *pDC = pictureConIDCam1-> GetDC( );

需要ReleaseDC

hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

涨到了多少?你是怎么看出泄露的?稍微增一点是正常的,只要不呈几何级数,请你把修改后的代码原样贴出来下
[/Quote]
源代码请见8楼。
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

涨到了多少?你是怎么看出泄露的?稍微增一点是正常的,只要不呈几何级数,请你把修改后的代码原样贴出来下
[/Quote]
以5M/s的速度增长,直到反复弹出内存不足提示对话框
hurryboylqs 2012-04-23
  • 打赏
  • 举报
回复
涨到了多少?你是怎么看出泄露的?稍微增一点是正常的,只要不呈几何级数,请你把修改后的代码原样贴出来下
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

楼上正解,pStream没有释放,所以一直加。
另外说明两点:
VC++执行释放语句时会立即释放内存,不会慢。
多幅图形连续显示最好用DirectX,用GDI+有点慢。
[/Quote]
谢谢hhhh63,你提到的DirectX还真没用过,我得去试试。GDI+的确是慢啊!让我很无语,我现在有点担心目前的显示机制,根本无法让两组视频图像同时显示,但由于GDI显示本图像有问题,正苦于不知道该如何办。谢谢你的提示!
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

CreateStreamOnHGlobal(hGloabl,true, &pStream) 这个函数的第二个参数为TRUE表示hGlobal不用你去调用
GlobalFree来释放,而是在pStream的Release时自动释放内存,然而你后面没有调用IStream的Release 导致了内存泄露
[/Quote]
谢谢:hurryboylqs,我调试了一下,发现即便释放,问题依旧!修改后的释放代码如下:
graphics.Clear(0);//
GlobalUnlock(hGloabl);
//GlobalFree(hGloabl);
delete ImageBufferStructCam->bufImageAll;
delete ImageBufferStructCam;
image = 0;
delete image ;
memDC.SelectObject(pOld);
bitmap.DeleteObject();
graphics.ReleaseHDC(memDC.m_hDC);
pStream->Release();
memDC.DeleteDC();
pictureConIDCam1->ReleaseDC(pDC);
另外一点:由于整个代码中,我如果屏蔽掉Drawimage后,就不会出现内存泄露问题?这让我觉得是Drawimage导致的内存泄露,求确认!!!谢谢!!
hcl545 2012-04-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

1. 某些程序逻辑分支的内存释放不完整, 如下

if (hGloabl == NULL)
{
return 0;
....


2. CreateStreamOnHGlobal 创建没有释放对象
[/Quote]
谢谢zzz3265:对你提到的1,我用断点追踪了,发现程序基本不会进入if里面;对于2,我创建的CreateStreamOnHGlobal中, pStream于hGlobal都分别进行了释放,发现问题依旧!!谢谢
hhhh63 2012-04-23
  • 打赏
  • 举报
回复
楼上正解,pStream没有释放,所以一直加。
另外说明两点:
VC++执行释放语句时会立即释放内存,不会慢。
多幅图形连续显示最好用DirectX,用GDI+有点慢。
加载更多回复(3)

15,980

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 界面
社区管理员
  • 界面
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧