Как обрабатывать ошибки сегмента под 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. Вы можете обрабатывать и действительно восстанавливать, если у вас достаточно четкий контроль над вашим кодом, чтобы точно знать, в каком состоянии он находится в момент сбоя и как выполнить восстановление.