Как обрабатывать ошибки сегмента под Windows?

Как приложение Windows может обрабатывать ошибки сегментации? Под "ручкой" я имею в виду перехватывать их и, возможно, выводить описательное сообщение. Кроме того, было бы неплохо восстановить их, но я предполагаю, что это слишком сложно.

5 ответов

Решение

Используйте SEH для ранней обработки исключений и используйте SetUnhandledExceptionFilter, чтобы показать описательное сообщение.

Позвольте им аварийно завершить работу и пусть Windows Error Reporting справится с этим - под Vista+ вы также должны рассмотреть возможность регистрации в Restart Manager, чтобы у вас была возможность сохранить работу пользователя и перезапустить приложение (например, Word/Excel/ и т. Д.). делает)

Если вы добавите /EHa аргумент компилятора тогда try {} catch(...) поймает все исключения для вас, включая исключения SEH.
Вы также можете использовать __try {} __except {} что дает вам больше гибкости в том, что делать при обнаружении исключения. положить __try {} __except {} в целом main() Функция в некоторой степени эквивалентна использованию SetUnhandeledExceptionFilter(),

При этом вы должны также использовать правильную терминологию. "ошибка сегмента" является термином UNIX. на окнах нет ошибок сегментации. На окнах они называются "Access Violation Exceopnts"

C++ автономный пример о том, как использовать SetUnhandledExceptionFilter, вызывая ошибку записи и отображая хорошее сообщение об ошибке:

#include <windows.h>
#include <sstream>

LONG WINAPI TopLevelExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo)
{
  std::stringstream s;
  s << "Fatal: Unhandled exception 0x" << std::hex << pExceptionInfo->ExceptionRecord->ExceptionCode 
  << std::endl;

  MessageBoxA(NULL, s.str().c_str(), "my application", MB_OK | MB_ICONSTOP);
  exit(1);

  return EXCEPTION_CONTINUE_SEARCH;
}

int main()
{
   SetUnhandledExceptionFilter(TopLevelExceptionHandler);
   int *v=0;
   v[12] = 0;   // should trigger the fault
   return 0;
}

Успешно протестирован с g++ (и должно работать нормально с MSVC++)

Аналогично решению Жана-Франсуа Фабра, но с кодом Posix в MinGW-w64. Но обратите внимание, что программа должна завершиться - она ​​не может восстановиться с SIGSEGV и продолжить.

#include <stdio.h>
#include <signal.h>
#include <stdlib.h>

void sigHandler(int s)
{
    printf("signal %d\n", s);
    exit(1);
}

int main()
{
    signal(SIGSEGV, sigHandler);
    int *v=0;
    *v = 0;   // trigger the fault

    return 0; 
}

То, что вы хотите сделать здесь, зависит от того, с какими проблемами вы столкнулись. Если у вас есть неаккуратный код, который подвержен более или менее случайным нарушениям общей защиты, то ответ @Paul Betts - это то, что вам нужно.

Если у вас есть код, у которого есть веские основания полагаться на плохие указатели, и вы хотите восстановить его, начните с предложения @whunmr о SEH. Вы можете обрабатывать и действительно восстанавливать, если у вас достаточно четкий контроль над вашим кодом, чтобы точно знать, в каком состоянии он находится в момент сбоя и как выполнить восстановление.

Другие вопросы по тегам