Когда Windows Error Reporting создает файл дампа? Это настраивается? Изменилось ли это в Windows 7?

Я полагаюсь на Отчеты об ошибках Windows создавать полные дампы пользовательского режима для большого многопоточного приложения. Я знаю, что когда я начал использовать его (в начале 2012 года), эти дампы содержали всю память приложения и полные стеки для всех потоков, которые были точными на момент сбоя приложения (сгенерировал необработанное исключение и т. Д.). Но в какой-то неизвестный момент в прошлом году аварийные дампы, созданные WER, изменились. Они по-прежнему содержат всю память, но показывают только один поток, а стек выглядит как после процесс уже завершается:

    ntdll.dll!_LdrpCallInitRoutine@16()  + 0x14 bytes
ntdll.dll!_LdrShutdownProcess@0()  + 0x141 bytes
ntdll.dll!_RtlExitUserProcess@4()  + 0x74 bytes
kernel32.dll!_UnhandledExceptionFilter@4()  + 0x18928 bytes

Это неуправляемое (неуправляемое?) 32-битное приложение C ++, скомпилированное с VS2010 SP1, работающее на 64-битной Win7 SP1 (и постоянно обновляемое). Кто-нибудь знает какие-либо обновления Windows, которые изменили поведение WER за последний год? Есть ли что-то настраиваемое, кроме «HKLM \ SOFTWARE \ Microsoft \ Windows \ Отчеты об ошибках Windows \ LocalDumps \ AppName.exe»?

Кроме того, уничтожение приложения путем вызова RaiseFailFastException по-прежнему приводит к хорошему дампу с допустимыми стеками для всех потоков.

5

Решение

Ага! Сторонняя библиотека вызывала SetUnhandledExceptionFilter, что не позволяло отчетам об ошибках Windows получать исходное исключение. Их обработчик выполнил некоторую внутреннюю очистку, затем вызвал прерывание, после чего WER наконец смог создать дамп.

Для тех, кто сталкивается с такой проблемой, я рекомендую проверить, соответствуют ли установленные обработчики (возвращаемые значения SetUnhandledExceptionFilter, set_terminate и т. Д.) (Нулю, если вы полагаетесь на WER, или ваши собственные обработчики или CrashRpt).

4

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

Лучше сделать приложение самостоятельно записывающим дамп, когда оно падает. Вам просто нужно позвонить SetUnhandledExceptionFilter функция, укажите обратный звонок. В обратном звонке используйте MiniDumpWriteDump функция с MiniDumpWithFullMemory тип дампа.

Ваш фильтр исключений будет вызываться всякий раз, когда возникает необработанное (вашим кодом) исключение. При обратном вызове будет лучше перечислить и приостановить все остальные потоки вашего процесса.

Вам также может понадобиться установить крючок для SetUnhandledExceptionFilter сам! Зачем? Что ж, ЭЛТ всегда будет отключать любой установленный фильтр исключений, и с помощью подключенной функции вы можете избежать этого.

0