我有用 VS2008 编译的 Win32 MFC 应用程序。该应用程序具有 TreeConrtol。有一个 TVN_ITEMCHANGING 处理程序,在处理程序内部我强制重新绘制更改的树项。
这是带有 SEH 处理程序和直接 WinAPI 调用而不是 MFC 包装器的代码(这不会影响问题):
void CMainDlg::OnTvnItemChangingMainTree(NMHDR *pNMHDR, LRESULT *pResult)
{
NMTVITEMCHANGE *pNMTVItemChange = reinterpret_cast(pNMHDR);
HWND hTreeCtrl = _ctrlTree.GetSafeHwnd();
RECT rect;
__try
{
*(HTREEITEM*) &rect = hItem;
if ((BOOL) ::SendMessage(hTreeCtrl, TVM_GETITEMRECT,
(WPARAM) FALSE, (LPARAM) &rect))
{
::InvalidateRect(hTreeCtrl, &rect, TRUE);
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
::MessageBox(NULL, L"SEH exception is Here", L"__except Block", MB_OK);
}
*pResult = 0;
}
如果我在树控件中选择一个项目(以编程方式或通过鼠标单击),那么在从树控件中删除所有项目后(通过使用 DeleteAllItems 或一个接一个),我将获得已经没有的项目的 TVN_ITEMCHANGING存在,因此上面的代码在调用 ::SendMessage(hTreeCtrl, TVM_GETITEMRECT, ...) 时会导致结构化异常引发。
没关系,但是... __except 块永远不会在某些 Windows 8.1 Pro x64 上执行(可能在其他 Windows 版本上)。
我的工作机器是从 Windows 8 更新的英文 Windows 8.1 Pro x64(内部版本 9600)。在那台机器上一切正常(处理程序捕获异常并显示 MessageBox)。但是,在从 MSDN 下载的干净的英文 Windows 8.1 Pro x64(内部版本 9600)上,__except 块未被调用并且应用程序崩溃。故障模块名称:COMCTL32.dll
我在两台计算机上运行相同的 .exe 文件。您如何看待为什么会发生这种情况?
这是一个工作示例。我用 /EHsc 编译它,然后用 /EHa 编译它(真正的项目是用 /EHa 编译的,并使用 try/catch)。
示例中的代码与上面的函数不同:我添加了使用 try/catch 和_try / _except 的选项。
使用 /EHa,我可以在我的工作机器上使用 try/catch 或 _try / _except 捕获异常,使用 /EHsc 使用 _try / _except。但是这些组合都不适用于另一台机器(使用干净的 Win8.1):它不会捕获异常。
演示项目(使用 Visual Studio 2008 Professional SP1 + MFC 编译):这里.
PS:通过在 SendMessage() 调用中添加 if 条件暂时解决了问题,但这里我想调查一下异常处理的问题。
提前感谢您的评论。