前言
最近在做wince平台的上位机开发,因此用到了控件的重绘和图形的绘制,所以使用到了GDI。
但是在程序运行的过程中,发现wince6.0的运行内存不断增加,怀疑是GDI使用时,申请的内存未及时释放导致内存泄漏。
这是就需要了解如何正确释放申请的内存来避免内存泄漏。
正文
首先需要清楚的是,无论是CPen还是CBrush等类还是CDC,它们都有自己的申请和释放的对应关系:
new -> delete;
Malloc -> free;
Create -> Delete
GetDC -> ReleaseDC
具体的一些说明可查看我之前的博客:【MFC】GDI如何释放资源.
程序举例:
网上关于wince下串口编程的方法大同小异,下面贴出接收线程部分代码。
// A code block
DWORD MainDlg::PnPaint()
{
CPaintDC dc(this);
//内存DC
CDC dcMem;
if (!m_dcMem.CreateCompatibleDC(&dc))
{
return;
}
CBitmap bitmap;
bitmap.CreateBitmap(10, 10, 1, 32, NULL);
HBITMAP pOldBmp = (HBITMAP)dcMem.SelectObject(bitmap);
CBrush brush(RGB(0, 0, 255));
HGDIOBJ hOldBrush = dcMem.SelectObject(&brush);
CPen pen(PS_SOLID, 2, m_crNorthLineD)
CPen *pOldPen = dcMem.SelectObject(&pen);
dcMem.Ellipse(m_nCenterX - nXRadius, m_nCenterY - nYRadius, m_nCenterX + nXRadius, m_nCenterY + nYRadius);
//
dcMem.SelectObject(pOldBmp);
dcMem.SelectObject(hOldBrush);
dcMem.SelectObject(pOldPen);
//释放方法一:
bitmap.DeleteObject();
brush.DeleteObject();
pen.DeleteObject();
//释放方法二:
::DeleteObject(bitmap);
::DeleteObject(brush);
::DeleteObject(pen);
//
dcMem.DeleteDC();
}
通过上面的例程,可以知道内存的申请和释放的流程:
- 使用Create函数申请的内存,最终都需要DeleteObject释放;
- 在画刷等创建完成后,需要通过DC的SelectObject()函数将DC内原本的画刷替换掉,同时SelectObject()会返回旧的画刷,通过*pOld来储存;
- 在使用完创建的画刷等工具后,需要将旧的工具“还给”DC,这一个步骤是必须要执行的,否则你之后释放内存是无法正常释放的,因为工具始终被DC占用
- 释放的方法可以由例程中的方法一和方法二实现,同时若释放成功,DeleteObject()函数会返回非0值,可以起到一定的判断作用(但似乎有效性有待验证)
- 在工具也释放完成后,再将DC释放掉,DC如果是GetDC,释放则是ReleaseDC(),如果是CreateCompatibleDC,释放则是DeleteDC。
注意:
在WINCE系统下,使用::DeleteObject()函数无法正常释放函数,需要使用诸如CPen::DeleteObject()的方式来释放。