601 views
首页 > 技术心得 > 将 ATL 的一个顽固 Bug 修正了

将 ATL 的一个顽固 Bug 修正了

2008年7月2日

用 VC6 和 VC71 装载的 ATL 开发软件的人都知道, 当我们定义了一个自销毁窗口时, 一般在 ATL 窗口类的

virtual void OnFinalMessage(HWND ){…}

函数内加一句

delete this;

然后就返回了. 但是气人的是, 每次当我们返回后, 总有一个地方断言失败,

ATLASSERT(pThis->m_pCurrentMsg == &msg);

Google 了许久, 没有满意的解决方案, 包括微软的方案

http://support.microsoft.com/kb/202110

也不好, 自己想尽办法还是 “山重水复疑无路”, 后来突然灵光突现, 彻底解决, 就一个函数调用而已: IsWindow(…). 现在, 终极解决方案是这样的:
搜索 atlwin.h 文件内的 “ATLASSERT(pThis->m_pCurrentMsg == &msg);” 字符串 (在文件内有 3 处), 将其原始内容

LRESULT lRes;
BOOL bRet
= pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
// restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg);
pThis
->m_pCurrentMsg = pOldMsg;

改成

LRESULT lRes;
BOOL bRet
= pThis->ProcessWindowMessage(pThis->m_hWnd, uMsg, wParam, lParam, lRes, 0);
if(FALSE == ::IsWindow(pThis->m_hWnd)) {
return
lRes; // 在 CDialogImplBaseT 类里是 return FALSE;  特此说明
}
// restore saved value for the current message
ATLASSERT(pThis->m_pCurrentMsg == &msg);
pThis
->m_pCurrentMsg = pOldMsg;

其中红色的代码为我们的修正代码. 万事大吉. 再也不会出现断言失败了.

道理是这样的: 如果 pThis 对象被删除了的话, 那么 pThis 本身和其成员变量 m_hWnd 都将是一个无效值, 那么后续的操作将毫无意义. 因此直接返回, 不用废话.

真是简单的思路直指问题的核心啊.

技术心得

  1. 目前还没有任何评论.
  1. 目前还没有任何 trackbacks 和 pingbacks.