Почему Windows проглатывает исключения во время WM_CLOSE

17

Пытаясь выяснить, почему приложение, над которым я работаю, не закрылось, я понял, что оно вызывает исключение в обработчике WM_CLOSE . Однако вместо сбоя приложения (как и должно быть) исключение автоматически игнорируется.

Чтобы убедиться, что больше ничего не происходит, я создал новое приложение C32 Win32 в Visual Studio и добавил следующее:

case WM_CLOSE:
    (*(int*)NULL) = 0;
    break;

То же самое: без сбоев, только исключение из первого шанса в журнале отладки. Если я добавлю тот же код в обработчик WM_COMMAND , он вылетит, как и ожидалось.

Мне любопытно: что такого особенного в WM_CLOSE , что Windows считает, что вызванные ею исключения следует проглотить?

(Кстати: это на Windows 7 x64, работает программа x86)

    
задан Brad Robinson 12.05.2014 в 09:34
источник
  • В WM_CLOSE нет ничего особенного. Необработанные исключения в обратном вызове WndProc всегда бесшумно игнорируются, вызывая WndProc под обработчиком __try / __ except. Это единственная безопасная реализация, поскольку, когда вы передаете управление кадрами стека, все промежутки между ними должны быть в шутке. –  IInspectable 12.05.2014 в 09:52
  • По умолчанию вызовы WindoWProcedure уничтожают окно, чтобы уничтожить окно. Это может быть причиной того, что любые исключения затем перенаправляются на «/ dev / null»: msdn.microsoft.com/en-us/library/windows/desktop/... и msdn.microsoft.com/en-us/library/ окна / настольные / ... –  icbytes 12.05.2014 в 09:52
  • @Inpectable, я не думаю, что Раймонд Чен говорит, что обратный вызов WndProc защищен в своей статье. На самом деле похоже, что он говорит обратное: в результате этого общего мышления код Win32 не слишком беспокоится о восстановлении из-за исключения. Если произойдет исключение, значит, ваш процесс уже является тостом, и нет смысла пытаться его исправить. Кроме того, если обратный вызов был защищен, то разыменование указателя NULL также не будет сбой в обработчике WM_COMMAND. –  Frédéric Hamidi 12.05.2014 в 10:08
  • @Brad Если вы не хотите, чтобы ваши исключения проглатывались, вам нужно предоставить манифест, совместимый с Win7, с вашим приложением и скомпилировать для 64-битного. В противном случае действует «старое» поведение Win2k3, которое проглатывает исключения. –  IInspectable 12.05.2014 в 14:54
  • @Brad Наличие действительного манифеста Windows 7 достаточно для изменения поведения. Это подробно описано в случае исчезновения исключения OnLoad. Я должен был уточнить: не все исключения проглатываются по умолчанию, но только те, где WndProc - это обратный вызов функции ядра в режиме пользователя (например, WM_CREATE / WM_NCCREATE в результате вызова CreateWindow). –  IInspectable 12.05.2014 в 20:45
Показать остальные комментарии

1 ответ

2

То, что исключения будут поглощены WindowProc на Win 64, является ожидаемым поведением. ( см. документы .)

Также см. более подробные объяснения на блог Пола Беттса , особенно его заметка

How come this doesn’t happen all the time?

Here’s why this seems to happen only on certain window messages – remember that window messages can originate from different sources, anyone(*) can queue a message to a window. However, certain window messages are directly sent via win32k.sys (the most notable one being WM_CREATE) as a direct synchronous result of a user-mode call.

, кажется, пролил некоторый свет на этот вопрос.

Случайный ASCII также имеет хорошее объяснение всего этого Поведение ядра в режиме ex-swallowing:

Failure to stop at all

An equally disturbing problem was introduced some years ago with 64-bit Windows and it causes some crashes to be silently ignored.

Structured exception ... relies on being able to unwind the stack (without or without calling destructors) in order to transfer execution from where an exception occurs to a catch/__except block.

The introduction of 64-bit Windows complicated this. On 64-bit Windows it is impossible to unwind the stack across the kernel boundary. That is, if ... an exception is thrown in the callback that is supposed to be handled on the other side of the kernel boundary, then Windows cannot handle this.

This may seem a bit esoteric and unlikely – writing kernel callbacks seems like a rare activity – but it’s actually quite common. In particular, a WindowProc is a callback, and it is often called by the kernel, ...

И в качестве бонуса: см. здесь, на SO почему .

    
ответ дан Martin Ba 23.05.2017 в 14:32
  • Я думаю, что это ужасно и шокирует то, что Windows молча проглатывает исключения - что Windows молча игнорирует сбои. В статье Раймонда Чена указывается на опасность того, что исключения будут обработаны, если все не будут в курсе шутки, которая делает ее еще более странной, но Windows это делает. Кстати, я автор статьи Random ASCII, связанной с этим ответом. –  Bruce Dawson 06.06.2015 в 18:05
  • @BruceDawson - Я соглашаюсь на ужасное, тогда как все-таки я прошел через. Сбой при работе с Windows (начиная с XP), я не уверен, что я нахожу много шокирующим. :-) ... И спасибо за Random ASCII - всегда там отличные ресурсы! –  Martin Ba 12.06.2015 в 22:00