Могу ли я декодировать исключение С++ из исключения Windows SEH? (И если да, то как?)
В случае необработанного исключения С++ я хочу напечатать:
- Сообщение (
what()
) исключения С++
- Трассировка стека.
Чтобы получить трассировку стека, я использую SetUnhandledExceptionFilter
в сочетании с библиотекой StackWalker:
struct FooStackWalker : StackWalker
{
virtual void OnCallstackEntry(CallstackEntryType, CallstackEntry &entry) override
{
std::cerr << entry.lineFileName << " (" << entry.lineNumber << "): " << entry.undFullName << std::endl;
}
};
LONG WINAPI UnhandledExceptionHandler(LPEXCEPTION_POINTERS pointers)
{
FooStackWalker walker;
walker.ShowCallstack(::GetCurrentThread(), pointers->ContextRecord);
::TerminateProcess(::GetCurrentProcess(), 1);
}
int main()
{
::SetUnhandledExceptionFilter(UnhandledExceptionHandler);
}
Я получил трассировку стека, чтобы печатать очень хорошо, но теперь получить what
сложно.
Можно ли каким-либо образом декодировать исключение SEH как исключение С++ для вызова этой функции-члена до завершения?
Ответы
Ответ 1
Почему бы не использовать С++-машину, которая уже дает вам сведения об исключении? Он не является эксклюзивным с фильтрами SEH (хотя он является эксклюзивным с SetUnhandledExceptionFilter
). Вам просто нужно правильно вложить обработчики:
int main()
{
try {
return cppexcept_main();
}
catch (const std::exception& e)
{
//use e.what()
}
}
int cppexcept_main()
{
__try {
return application_main();
}
__except(GrabStackTrace(GetExceptionInformation()), EXCEPTION_CONTINUE_SEARCH) {
/* never reached due to EXCEPTION_CONTINUE_SEARCH */
}
}
Ответ 2
Изменить. Я неправильно понял ваш вопрос. Я не могу точно сказать, что ответ за исключения С++, но я уверен, что ответ "нет". Я не верю, что существует какой-либо способ отличить необработанные исключения, вызванные SEH (например, нарушениями доступа) и неотображаемыми исключениями С++, или любым способом различать различные типы исключений С++. Лошадь уже оставила сарай на этом.
Оригинальный ответ ниже:
Нет, поскольку исключение SEH не имеет what
. Это не a std::exception
. В этом примере MSDN говорится, что когда вы пытаетесь поймать исключение SEH как исключение С++, его можно поймать только с помощью многоточия (...
) catch
. Вы можете использовать _set_se_translator
, чтобы определить свою собственную функцию, которая преобразует исключения SEH в исключения С++, но в этот момент вы просто генерируете свой собственный what
из той же информации в другом месте (и даже тогда я не знаю, можно ли получить ее от UnhandledExceptionFilter
).
У вас есть вся необходимая информация в структуре LPEXCEPTION_POINTERS
. Если произошло нарушение доступа, то pointers->ExceptionRecord->ExceptionCode
будет EXCEPTION_ACCESS_VIOLATION
(0xC0000005). Если это произошло, вы можете проверить переменные NumberParameters
и ExceptionInformation
, чтобы выяснить, было ли это нарушение чтения или записи и адрес, к которому был осуществлен доступ.