Структурный обработчик исключений (SEH) не улавливает повреждение кучи
Я пишу небольшую утилиту (VC 2010, no clr), которая выполняет одну простую задачу (растеризацию) с использованием сторонней библиотеки. Позже утилита будет использоваться большим приложением. Иногда утилита вылетает из-за некоторого повреждения кучи в сторонней библиотеке. Это нормально, но Windows (Vista/2008) показывает хорошо известный диалог "Программа перестала работать... Закрыть / Отладить программу". что не подходит в моем случае (на стороне сервера). Утилита должна аварийно завершить работу / прекратить работу без видимых эффектов.
Для этого я установил SEH для необработанного исключения (SetUnhandledExceptionFilter). Обработчик отлично вызывается для исключений, таких как AV ( *(PDWORD)0 = 0), но по какой-то причине он не вызывается в случае повреждения кучи. Повреждение происходит в dllmain одного из библиотек dll сторонних производителей во время его выгрузки.
Пара вопросов. Кто-нибудь может объяснить, почему обработчик не вызывается? Есть ли другой способ предотвратить этот диалог?
2 ответа
Очевидно, это намеренно, что повреждения кучи не могут быть обнаружены определяемыми пользователем обработчиками исключений, даже если они генерируются как исключения со своим собственным кодом исключения (0xC0000374 "STATUS_HEAP_CORRUPTION"). Вот отчет об ошибке в Visual C++, который в основном был закрыт как "не будет исправлено":
Как вы обнаружили, это не ошибка компилятора или ОС. Повреждение кучи, вызываемое вашей функцией, рассматривается как критическая ошибка, и как часть обработки этой ошибки ОС завершает процесс. Это то, что заставляет ваши обработчики исключений не вызываться.
Я предполагаю, что Windows Error Reporting или другие способы создания аварийного дампа все еще могут его поймать.
Что касается предотвращения диалога, в реестре вы можете либо полностью отключить WER, либо просто отключить диалог, чтобы процесс не блокировался:
https://msdn.microsoft.com/de-de/library/windows/desktop/aa366711(v=vs.85).aspx (см. "DontShowUI")
но по какой-то причине это не вызывается в случае повреждения кучи. Повреждение происходит в dllmain одного из библиотек dll сторонних производителей во время его выгрузки.
Повреждение кучи - неопределенное поведение. Это может вызвать исключения, это может сделать иначе. Если в вашей куче глючит сторонняя библиотека, то возникает вопрос: "Почему вы позволяете им в первую очередь связываться с вашей кучей?"
Диалог "Программа перестала работать" отображается всякий раз, когда процесс завершается ненормально. Не все ненормальные завершения процесса являются результатом исключений. Многие ошибки (такие как переполнение стека, неправильно выровненный стек и т. Д.) Вызывают мгновенное завершение процесса, которое может показать это сообщение, но не даст вам возможности обработать ошибку.
(Также см. Потрясающий комментарий Ганса выше)