定位MFC程序GDI对象泄漏过程中的一些经验

来源:互联网 发布:淘宝网店如何装修 编辑:程序博客网 时间:2024/05/16 13:56

定位MFC程序GDI对象泄漏过程中的一些经验

之前接触MFC比较少,最近一个程序需要使用MFC写界面。写完之后发现程序运行一段时间后异常卡顿,并且WIN7系统任务栏图标出现一些毛边等异常情况。重新运行程序,打开任务管理器发现GDI对象不断增加,且数量到达9999后程序开始异常。因此判断程序可能存在GDI对象泄漏,即创建的GDI对象没有及时释放。
鉴于GDI对象不断自动增加,判断GDI泄漏可能位于定时器触发的OnTimer函数中。OnTimer函数调用方法如下:

 LRESULT CVServerView::OnChangeTime(WPARAM wParam, LPARAM lParam) {     CString strText;     FormatTime((INT)wParam, 30, strText);     m_editPush.SetWindowText(strText);     return 0; }

可以看出函数仅仅是调用了API函数SetWindowText,理论上不应该导致GDI泄漏。但奇怪的是注释掉SetWindowText后程序就正常了。后来发现原因在于程序重写了OnCtlColor函数。

HBRUSH CVServerView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){    HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);    // TODO:  在此更改 DC 的任何特性    if (pWnd->GetDlgCtrlID() == IDC_EDIT_PUSH) {        pDC->SetBkMode(TRANSPARENT);        pDC->SetTextColor(RGB(255, 255, 255));        return HBRUSH(CreateSolidBrush(RGB(56, 56, 56)));    }    // TODO:  如果默认的不是所需画笔,则返回另一个画笔    return hbr;}

SetWindowText函数会调用以上OnCtlColor函数。OnCtlColor中CreateSolidBrush创建了GDI对象没有释放导致GDI对象不断增加,这就是问题所在。因此将程序修改为创建一个全局画笔m_brushBack=CreateSolidBrush(RGB(56, 56, 56)),OnDestroy时释放掉。修改代码如下:

HBRUSH CVServerView::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor){    HBRUSH hbr = CFormView::OnCtlColor(pDC, pWnd, nCtlColor);    // TODO:  在此更改 DC 的任何特性    if (pWnd->GetDlgCtrlID() == IDC_EDIT_PUSH) {        pDC->SetBkMode(TRANSPARENT);        pDC->SetTextColor(RGB(255, 255, 255));        return HBRUSH(m_brushBack);    }    // TODO:  如果默认的不是所需画笔,则返回另一个画笔    return hbr;}

回头再看,问题很简单并且出现在细节地方,主要原因在于自己对GDI对象管理了解太少,随意创建GDI对象不及时释放。以此提醒自己需要牢记GDI对象创建及释放问题。

0 0
原创粉丝点击