Подтвердить что ты не робот

Могу ли я декодировать исключение С++ из исключения 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 как исключение С++ для вызова этой функции-члена до завершения?

4b9b3361

Ответ 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, чтобы выяснить, было ли это нарушение чтения или записи и адрес, к которому был осуществлен доступ.