帮忙找一下内存泄漏在哪里

wubicheng 2013-08-13 10:01:36
程序是用Win32 API写的。
这只是核心代码,其中Render会被不断循环调用,这个只是一个我用来测试的程序,原程序比这复杂得多,但是出问题的与这部分代码功能一样,只是所加载的图片不是固定的,而是一直在变。
程序一跑起来就可以看到内存开始缓慢增长,因为只有一张图的资源在泄漏,涨的不是很快,但是我可以肯定的是如果放着不管,几个小时后我电脑内存就会爆掉,我怀疑是CImage造成的内存泄漏,在网上搜了好多这方面的信息,都不能解决我的问题,不要说用ReleaseGDIPlus,这个函数一样不行,已经试过了。

void Render(HINSTANCE hInst,int iCurTime)
{
HDC hdc=GetDC(g_hWnd);
ImageFromIDResource(hInst,IDB_PNG1,TEXT("PNG"));
g_hBgMap=g_image.Detach();
SelectObject(g_mdc,g_hBgMap);
BitBlt(hdc,0,0,362,265,g_mdc,0,0,SRCCOPY);
DeleteObject(g_hBgMap);
ReleaseDC(g_hWnd,hdc);
}
void ImageFromIDResource(HINSTANCE hInst,UINT nID,LPCTSTR lpType)
{
HRSRC hRsrc = FindResource(hInst,MAKEINTRESOURCE(nID),lpType);

if(hRsrc == NULL)
return;

DWORD dwLen = SizeofResource(hInst, hRsrc);

BYTE* lpRsrc = (BYTE*)LoadResource(hInst, hRsrc);

if (!lpRsrc)
return;

HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, dwLen);
BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
memcpy(pmem,lpRsrc,dwLen);
IStream* pstm;
CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);

g_image.Destroy();//在Load前先释放掉上一次的内存。
g_image.Load(pstm);
GlobalUnlock(m_hMem);
pstm->Release();
FreeResource(lpRsrc);
}
...全文
201 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
xiaohuh421 2013-08-14
  • 打赏
  • 举报
回复
引用 7 楼 wubicheng 的回复:
[quote=引用 6 楼 xiaohuh421 的回复:] void Render(HINSTANCE hInst,int iCurTime) { HDC hdc=GetDC(g_hWnd); ImageFromIDResource(hInst,IDB_PNG1,TEXT("PNG")); g_hBgMap=g_image.Detach(); SelectObject(g_mdc,g_hBgMap); //这里SelectObject有与之对应的SelectObject吗, 没有的话就会泄漏 BitBlt(hdc,0,0,362,265,g_mdc,0,0,SRCCOPY); DeleteObject(g_hBgMap); ReleaseDC(g_hWnd,hdc); }
呃,SelectObject对应SelectObject??是与之对应的DeleteObject吧?你的注释再往下两行不就是DeleteObject了吗? 还是说我理解错你的意思了,那你再说详细点? SelectObject(g_mdc,g_hBgMap)之后, 需的再Select回去, 然后再删除掉原来的东西. MSDN中说明 Remarks This function returns the previously selected object of the specified type. An application should always replace a new object with the original, default object after it has finished drawing with the new object. 意思说 你选择了一个新的Object到DC中, 在使用完成后需在再把原来的Object选择回DC中, 再然再删除那个新的Object. 所以说需要两个SelectObject对应. 下面类似的伪代码. HDC hDC = ...; HBITMAP hBmp=...;//新的Object HBITEM hOld = SelectObject(hDc, hBmp);//选入新的Object, 同时保存旧的Object BitBlt(....); //使用新的Object做一些事 SelectObject(hDc, hOld); //把旧的Object选回去 DeleteObject(hBnp); //再释放新的Object. ....... //释放其它资源.
赵4老师 2013-08-14
  • 打赏
  • 举报
回复
虎头蛇尾是俗人的习惯, 有始有终是君子的操守。 {;} malloc;free new;delete new[];delete[] CreateBitmap, CreateBitmapIndirect, CreateBrushIndirect, CreateCompatibleBitmap, CreateDIBitmap, CreateDIBPatternBrush, CreateEllipticRgn, CreateEllipticRgnIndirect, CreateFont, CreateFontIndirect, CreateHatchBrush, CreatePatternBrush, CreatePen, CreatePenIndirect, CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect, CreateSolidBrush ;BOOL DeleteObject(HGDIOBJ hObject);// handle to graphic object GlobalAlloc;GlobalFree LocalAlloc;LocalFree HeapAlloc;HeapFree VirtualAlloc;VirtualFree 借;还 生;死
wubicheng 2013-08-14
  • 打赏
  • 举报
回复
呵呵,8楼说对了,我一开始不了解GlobalAlloc,以为pstm->Release();就把内存释放了,刚刚查MSDN才发现原来这个要通过GlobalFree来释放,然后我把这个加上去后就没问题了,谢谢大家了哈,这个问题解决了。
引用 10 楼 zhao4zhong1 的回复:
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
然后是赵大神你这个方法适用范围广,但是一般来说没有人能等得了一个月的,一个小时都不用等,如果真有内存泄漏,数据我不知道增长速度怎么样,从没在数据上犯过内存泄露的错误,但是对于图片这样的资源,基本上2~3分钟就可以看到内存使用量上升一个百分点,图片大增长的更快,图片小10分钟也可以看出来,当然,我这说的是2G内存下。
赵4老师 2013-08-14
  • 打赏
  • 举报
回复
检查是否资源泄漏的办法之一: 在任务管理器 进程 查看 选择列 里面选择:内存使用、虚拟内存大小、句柄数、线程数、USER对象、GDI对象 让你的程序(进程)不退出,循环执行主流程很多遍,越多越好,比如1000000次甚至无限循环,记录以上各数值,再隔至少一小时,越长越好,比如一个月,再记录以上各数值。如果以上两组数值的差较大或随时间流逝不断增加,则铁定有对应资源的资源泄漏!
mujiok2003 2013-08-14
  • 打赏
  • 举报
回复
引用 7 楼 wubicheng 的回复:
[quote=引用 6 楼 xiaohuh421 的回复:] void Render(HINSTANCE hInst,int iCurTime) { HDC hdc=GetDC(g_hWnd); ImageFromIDResource(hInst,IDB_PNG1,TEXT("PNG")); g_hBgMap=g_image.Detach(); SelectObject(g_mdc,g_hBgMap); //这里SelectObject有与之对应的SelectObject吗, 没有的话就会泄漏 BitBlt(hdc,0,0,362,265,g_mdc,0,0,SRCCOPY); DeleteObject(g_hBgMap); ReleaseDC(g_hWnd,hdc); }
呃,SelectObject对应SelectObject??是与之对应的DeleteObject吧?你的注释再往下两行不就是DeleteObject了吗? 还是说我理解错你的意思了,那你再说详细点?
引用 5 楼 mujiok2003 的回复:
试试智能指针

//IStream* pstm;
CComPtr<IStream> pstm;
表示不行,我试了,还是内存泄漏,不是Release的问题。[/quote] 你该使用内存泄露检测工具了:vld很简单易用。
mstlq 2013-08-14
  • 打赏
  • 举报
回复
貌似代码里没有看到与GlobalAlloc对应的GlobalFree...
wubicheng 2013-08-14
  • 打赏
  • 举报
回复
引用 6 楼 xiaohuh421 的回复:
void Render(HINSTANCE hInst,int iCurTime) { HDC hdc=GetDC(g_hWnd); ImageFromIDResource(hInst,IDB_PNG1,TEXT("PNG")); g_hBgMap=g_image.Detach(); SelectObject(g_mdc,g_hBgMap); //这里SelectObject有与之对应的SelectObject吗, 没有的话就会泄漏 BitBlt(hdc,0,0,362,265,g_mdc,0,0,SRCCOPY); DeleteObject(g_hBgMap); ReleaseDC(g_hWnd,hdc); }
呃,SelectObject对应SelectObject??是与之对应的DeleteObject吧?你的注释再往下两行不就是DeleteObject了吗? 还是说我理解错你的意思了,那你再说详细点?
引用 5 楼 mujiok2003 的回复:
试试智能指针

//IStream* pstm;
CComPtr<IStream> pstm;
表示不行,我试了,还是内存泄漏,不是Release的问题。
xiaohuh421 2013-08-14
  • 打赏
  • 举报
回复
void Render(HINSTANCE hInst,int iCurTime) { HDC hdc=GetDC(g_hWnd); ImageFromIDResource(hInst,IDB_PNG1,TEXT("PNG")); g_hBgMap=g_image.Detach(); SelectObject(g_mdc,g_hBgMap); //这里SelectObject有与之对应的SelectObject吗, 没有的话就会泄漏 BitBlt(hdc,0,0,362,265,g_mdc,0,0,SRCCOPY); DeleteObject(g_hBgMap); ReleaseDC(g_hWnd,hdc); }
mujiok2003 2013-08-14
  • 打赏
  • 举报
回复

 HGLOBAL m_hMem = GlobalAlloc(GMEM_FIXED, dwLen);
    BYTE* pmem = (BYTE*)GlobalLock(m_hMem);
    memcpy(pmem,lpRsrc,dwLen);
    IStream* pstm;
    CreateStreamOnHGlobal(m_hMem,FALSE,&pstm);
 
    g_image.Destroy();//在Load前先释放掉上一次的内存。
    g_image.Load(pstm);
    GlobalUnlock(m_hMem);
    pstm->Release(); //估计这里没有释放内存
    FreeResource(lpRsrc);
试试智能指针

//IStream* pstm;
CComPtr<IStream> pstm;
wubicheng 2013-08-14
  • 打赏
  • 举报
回复
引用 3 楼 starytx 的回复:
建议将循环调用的函数中的dc等相关资源在外部申请和释放,避免在循环中频繁申请释放
dc资源在循环内部频繁申请释放只是在我这个测试程序里,原程序用的是全局dc,释放只在WM_DESTROY中进行,但资源泄漏依然存在,问题不是出在这里。
引用 2 楼 max_min_ 的回复:
自己的写的代码,最清除那里进行的内存分配,那里进行堆空间的申请阿! 而且更加清楚那里去作响应的释放空间的!
我也知道啊,但是我已经反复检查了自己的代码,实在是没有查出什么问题,而且这个测试程序代码极为简单,就是不断的将某张PNG图片贴到客户区里,如果说原程序过于复杂,不好查错,那这个简单的程序也找不出错误的原因,我能有什么办法,无奈啊。
引用 1 楼 zhctj159 的回复:
确定使用GlobalAlloc没问题?
这个确实不好说,因为ImageFromIDResource那个函数不是我自己写的,我不是太清楚,当时只是发现它可以使得CImage可以从资源中导入PNG图片,就很高兴的用了。你这么一说,我觉得确实有可能是他这个函数释放内存不够彻底,我去查查这几个函数。
starytx 2013-08-14
  • 打赏
  • 举报
回复
建议将循环调用的函数中的dc等相关资源在外部申请和释放,避免在循环中频繁申请释放
max_min_ 2013-08-14
  • 打赏
  • 举报
回复
自己的写的代码,最清除那里进行的内存分配,那里进行堆空间的申请阿! 而且更加清楚那里去作响应的释放空间的!
zhctj159 2013-08-14
  • 打赏
  • 举报
回复
确定使用GlobalAlloc没问题?

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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