大白天的见活鬼,十分的无语:
在一个 CDialog 中写了个 Timer ,Timer中有一段用 GDI 绘图的代码如下:
void WaveDlg::OnTimer(UINT_PTR nIDEvent)
{
CWnd *pWave=GetDlgItem(IDC_WAVE);
CClientDC pdc(pWave);
}
很好,就这两行代码,其他的啥也没有,运行期间没有任何内存泄露。
可以注意到,我申请了一个 pdc ,并且没有去手写任何代码去释放它,因为我认为 CClientDC pdc(pWave); 这条语句所生成的对象,会在 OnTimer 函数结束时,自动析构。事实也是如此,就这两行代码,没有任何内存泄露,我特意把 Timer 的触发时间调整为 1ms,触发快,内存泄露明显,不用慢慢等。
OK,接着来,修改代码如下:
void WaveDlg::OnTimer(UINT_PTR nIDEvent)
{
CWnd *pWave=GetDlgItem(IDC_WAVE);
CClientDC pdc(pWave);
CBrush brsWhite;
brsWhite.CreateSolidBrush(RGB(255,255,255));
pdc.SelectObject(brsWhite);
::DeleteObject(brsWhite.m_hObject);
}
运行,内存一“泄”千里。。。。
无奈,再次尝试,修改代码如下:
void WaveDlg::OnTimer(UINT_PTR nIDEvent)
{
CWnd *pWave=GetDlgItem(IDC_WAVE);
CClientDC pdc(pWave);
CBrush brsWhite;
brsWhite.CreateSolidBrush(RGB(255,255,255));
pdc.SelectObject(brsWhite);
::DeleteObject(brsWhite.m_hObject);
::ReleaseDC(pWave->m_hWnd,pdc.m_hDC);
}
运行,不漏了。。。。
总结,在某个函数中,申请了一个局部的 CDC 后,如果,不对它进行修改,比如用它去 selectobject 某些对象,或者,不用它去画图,那么,可以不用手写代码去释放它。但是,一旦引用了这个 CDC 做了某些工作,那么,就需要手写代码去释放它了。。。
最后,为了保险起见,将所有的 CPen,CBrush 都声明为类成员,而不是局部变量,只在类成员初始化的时候,对他们调用一次 Create ,避免在局部函数中反复对他们调用 Create,避免内存泄露