最近写程序检查某个工程的内存泄漏问题,检查很久,修修补补,也补了部分内存泄漏问题,但是在画界面部分还是存在内存泄漏,而且经常间歇性才发作,百思不得其解,找了很多资料无果,只能自己一句句代码查找,功夫不负有心人最后让我发现了。。。
原来有内存泄漏的代码:
void CWinXXXDlg::OnPaint()
{
CDC dcMem;
CBitmap bmpMem;
BITMAP bm2;
CBitmap *pOldBm2=NULL;
dcMem.CreateCompatibleDC(&dc);
bmpMem.CreateCompatibleBitmap(&dc,800,480);
CBitmap *pOldBm=dcMem.SelectObject(&bmpMem);
CDC dcMem2;
dcMem2.CreateCompatibleDC(&dcMem);
CBitmap bmpMem2;
bmpMem2.Attach(::LoadBitmap( AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_BACKGROUND))); //背景
bmpMem2.GetBitmap(&bm2);
pOldBm2=dcMem2.SelectObject(&bmpMem2);//选BITMAP
dcMem.BitBlt(0,0,800,480,&dcMem2,0,0,SRCCOPY); //画背景位图
dcMem2.SelectObject(pOldBm2);//选回旧的bitmap进行清理内存
bmpMem2.Detach();
dcMem.SelectObject(pOldBm);//选回旧的bitmap进行清理
bmpMem.DeleteObject();
bmpMem2.DeleteObject();
dcMem.DeleteDC();
dcMem2.DeleteDC();
}
咋一看,好像没什么问题。
这程序在Timer中每100ms 运行一次this->Invalidate(0),我测试的WINCE 6中运行一直内存稳定,但是到了1个小时左右内存会迅速以4KB的速度一直减少
一直想不明白,最后发现原来是LoadBitmap惹的祸。
原程序中为了方便,将Attach和LoadBitmap写在了一条语句,但是LoadBitmap会返回一个HBITMAP的GDI句柄,MSDN中说到:
The application must call the DeleteObject function to delete each bitmap handle returned by the LoadBitmap function.
就是因为写在了一条语句上,所以忽略了它的返回值,导致有句柄没有删除引起内存泄漏。
原因知道了,下面改写代码:
void CWinXXXDlg::OnPaint()
{
CDC dcMem;
CBitmap bmpMem;
BITMAP bm2;
CBitmap *pOldBm2=NULL;
dcMem.CreateCompatibleDC(&dc);
bmpMem.CreateCompatibleBitmap(&dc,800,480);
CBitmap *pOldBm=dcMem.SelectObject(&bmpMem);
CDC dcMem2;
dcMem2.CreateCompatibleDC(&dcMem);
CBitmap bmpMem2;
HBITMAP hbitmap=::LoadBitmap( AfxGetInstanceHandle(), MAKEINTRESOURCE(IDB_BITMAP_BACKGROUND));//改成返回hbitmap
bmpMem2.Attach(hbitmap); //通过句柄进行Attach背景
bmpMem2.GetBitmap(&bm2);
pOldBm2=dcMem2.SelectObject(&bmpMem2);//选BITMAP
dcMem.BitBlt(0,0,800,480,&dcMem2,0,0,SRCCOPY); //画背景位图
dcMem2.SelectObject(pOldBm2);//选回旧的bitmap进行清理内存
DeleteObject(hbitmap);//最后还要使用这个删除HBITMAP句柄
bmpMem2.Detach();
dcMem.SelectObject(pOldBm);//选回旧的bitmap进行清理
bmpMem.DeleteObject();
bmpMem2.DeleteObject();
dcMem.DeleteDC();
dcMem2.DeleteDC();
}