Не всегда можно поймать SEH на WoW64 на «чистой» Windows 8.1

У меня есть приложение Win32 MFC, скомпилированное с VS2008. В приложении есть 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.1 Pro x64 (сборка 9600), обновленная с Windows 8. На этой машине все работает нормально (обработчик перехватывает исключение и отображается MessageBox). Однако на чистой английской Windows 8.1 Pro x64 (сборка 9600), загруженной из MSDN, блок __except не вызывается и происходит сбой приложения. Имя модуля неисправности: COMCTL32.dll

я бегу тот же файл .exe на обоих компьютерах. Как вы думаете, почему это может произойти?

Вот рабочий пример. Я скомпилировал его с / EHsc, а затем с / EHa (настоящий проект был скомпилирован с / EHa и использует try / catch).

Код в примере отличается от функции, описанной выше: я добавил опции для использования try / catch и _пытаться/_Кроме.

Используя / EHa, я могу поймать исключение, используя как try / catch, так и _пытаться/_except на моей рабочей машине, используя / EHsc используя _пытаться/_Кроме. Но ни одна из этих комбинаций не работает для другой машины (с чистой Win8.1): она не ловит исключение.

Демонстрационный проект (скомпилирован с Visual Studio 2008 Professional SP1 + MFC): Вот.

PS: проблема была временно решена путем добавления условия if к вызову SendMessage (), но здесь я хочу исследовать проблему с обработкой исключений.

Заранее благодарю за ваши комментарии.

1

Решение

Вы не контролируете все кадры между RaiseException (или эквивалент) и __try/__except: Есть SendMessage() позвонить в промежутке.

Раймонд Чен объяснил это лучше всего: Когда вы передаете управление через кадры стека, все кадры между ними должны быть включены в шутку

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]