CE的一次内存检漏

分类:MFC 标签:MFC, IT, 编程, WinCE

最近做的CE项目有个问题, 程序跑一段时间就白屏.
用各种工具看了半天也没发现内存有涨, 但是出这状况一般是内存泄露之类, 程序能跑是没什么问题.
于是压力测试, 最终发现停止刷新界面的话不会白屏, 一旦刷新次数过多就会白屏.
内存泄露锁定在重绘的地方, OnPaint()函数中
void CDlgXXX::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	CDC MemDc;
	CDC BmpDc;
	CBitmap MemBmp;
	MemDc.CreateCompatibleDC(&dc);	//兼容DC
	BmpDc.CreateCompatibleDC(&dc);	//兼容DC
	MemBmp.CreateCompatibleBitmap(&dc, SCREEN_WIDTH, SCREEN_HEIGHT);	//兼容位图
	MemDc.SelectObject(&MemBmp);
	MemDc.SetBkMode(TRANSPARENT);	//DC透明
	BmpDc.SetBkMode(TRANSPARENT);
	//MemDc.FillRect(&rt, &NewBrush);	//刷背景
	/****************************界面绘制****************************/
	BmpDc.SelectObject(&m_bmpStat);	//状态栏
	MemDc.BitBlt(0, 0, SCREEN_WIDTH, STATBAR_HEIGHT, &BmpDc, 0, 0, SRCCOPY);
	......
	/****************************绘制收尾****************************/
	dc.BitBlt(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, &MemDc, 0, 0, SRCCOPY);	//拷贝到屏幕

	MemBmp.DeleteObject();
	BmpDc.DeleteDC();
	MemDc.DeleteDC();	//释放兼容DC
	// 不为绘图消息调用 CDialog::OnPaint()
}
乍一看MemBmp, BmpDc, MemDc都释放了, 似乎看不出问题, 查了一下得知CE下DeleteObject的返回值解释为:
Return Value
Nonzero indicates success.
Zero indicates that the specified handle is not valid or that the handle is currently selected into a device context.
To get extended error information, call GetLastError.
如果当前Object正在被选中, DeleteObject()会失败, 看了一下返回值, 果然返回0, 失败了....
于是修改代码
void CDlgXXX::OnPaint()
{
	CPaintDC dc(this); // device context for painting
	// TODO: 在此处添加消息处理程序代码
	CDC MemDc;
	CDC BmpDc;
	CBitmap MemBmp;
	MemDc.CreateCompatibleDC(&dc);	//兼容DC
	BmpDc.CreateCompatibleDC(&dc);	//兼容DC
	MemBmp.CreateCompatibleBitmap(&dc, SCREEN_WIDTH, SCREEN_HEIGHT);	//兼容位图
	CBitmap *pOldBmp_MemDc = MemDc.SelectObject(&MemBmp);
	MemDc.SetBkMode(TRANSPARENT);	//DC透明
	BmpDc.SetBkMode(TRANSPARENT);
	//MemDc.FillRect(&rt, &NewBrush);	//刷背景
	/****************************界面绘制****************************/
	CBitmap *pOldBmp_BmpDc = BmpDc.SelectObject(&m_bmpStat);	//状态栏
	MemDc.BitBlt(0, 0, SCREEN_WIDTH, STATBAR_HEIGHT, &BmpDc, 0, 0, SRCCOPY);
	......
	/****************************绘制收尾****************************/
	dc.BitBlt(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT, &MemDc, 0, 0, SRCCOPY);	//拷贝到屏幕

	BmpDc.SelectObject(pOldBmp_BmpDc);
	MemDc.SelectObject(pOldBmp_MemDc);
	MemBmp.DeleteObject();
	BmpDc.DeleteDC();
	MemDc.DeleteDC();	//释放兼容DC
	// 不为绘图消息调用 CDialog::OnPaint()
}
编译测试, 未发现问题.
于是, 绘图资源释放前, 一定要选回原来的Object. 前车之鉴.
你可能还会对下列文章感兴趣:

0条评论 你不想来一发么↓

    想说点什么呢?

    您需要登录您的Google账号才能进行评论。