…вид. Как показано на этом чрезвычайно упрощенном примере,
очень редко (пока сообщалось только один раз), случается, что одно из моих приложений падает таким образом. Я хочу прекратить его, как обычно, когда происходит неопределенное исключение. Моя стратегия состоит в том, чтобы (на низком уровне) зарегистрировать проблему, а затем завершить ее. Приложение является частью подсистемы, и я хочу (пере) запустить его, если обнаружится какая-либо проблема. Он построен на C ++ — Builder 6 и работает в Windows (XP … 7, также 8). Я узнал, что abort()
скорее всего, вызвало сообщение об ошибке. Приложение имеет графический интерфейс, поэтому вместо вывода (разблокировки) вывода сообщения отображается окно сообщения. stderr
,
И пока окно сообщения не будет принято пользователем, мое приложение явно работает, например, он обрабатывает таймеры (количество ударов в приведенном выше примере увеличивается) или межпроцессные сообщения, совершенно не подозревая о проблеме.
Прочитав некоторые ответы на Какой самый простой способ вызвать сбой программы на C ++? а также Разница между методами повышения (SIGABRT) и abort (), Я попробовал следующее
void mySignalHandler(int sig)
{
// low-level error reporting here
exit(-1);
}
void __fastcall TForm1::FormCreate(TObject *Sender)
{
signal(SIGABRT, mySignalHandler);
// some more initialisation here
}
что позволяет моему приложение прекращается правильно также, если abort()
или же raise(SIGABRT)
называется. (Я также хочу запретить Windows «искать решение проблемы».)
Надежно ли это (регистрация обработчика сигнала для прерывания и вызова выхода там) с вашей точки зрения? … или хотя бы что-то, на что можно опираться?
В папке установки C ++ Builder проверьте следующие файлы:
_ErrorMessage
abort
, который вызывает _ErrorMessage
_assert
, который вызывает _ErrorMessage
errormsg.c определяет недокументированное _messagefunc
указатель функции, который вы можете установить для переопределения поведения по умолчанию. Хотя он недокументирован и не объявлен ни в одном из заголовочных файлов, вы можете объявить его как extern
и получить к нему доступ таким образом. Пример использования:
extern int (_RTLENTRY * _EXPDATA _messagefunc)(char *msg);
static int LogAndDie(char *msg)
{
LogMessageToSomeFile(msg);
exit(1);
return 0;
}
void InitializeErrorHandling()
{
_messagefunc = LogAndDie;
}
Возможно, вы сможете использовать отчеты об ошибках Windows для создания дампа процесса, когда необработанное исключение вызывает завершение. Затем вы можете просмотреть дамп на досуге и позволить некоторым родительским процессам или другим сторожевым таймерам перезапустить ваш процесс. Если бы вы выбрали эту стратегию, вы бы не попытаться справиться с ошибкой в вашем коде, но разрешить это.
Если вы хотите захватить любой выход программы, вы должны посмотреть на atexit (). Если вы хотите захватить все события завершения, посмотрите на станд :: set_terminate (), если вы хотите скрыть все неожиданные исключения, посмотрите на станд :: set_unexpected (). Если вы хотите захватить только abort()
ты можешь позвонить сигнал() с SIGABRT
значение сигнала. Вы также можете обернуть свой код с try{your code}catch(...){custom event handler}
,
Я мог бы сделать несколько тестов, и я могу только подтвердить, что регистрация обработчика сигнала SIGABRT — это просто NOOP.
Я попробовал это с очень простым приложением GUI, написанным с Экспрессом VS2008. :
Вот результат:
Если я ставлю обработчики бота SEH, ловит самый внутренний (WndProc).
Хороший новый для вас, что если довольно чтобы защитить цикл сообщений, и вам не нужно заходить в каждый WndProc.
Плохо то, что я не знаю C ++ Builder и не могу сказать, где найти цикл сообщений.
Просто, чтобы дать вам подсказку, вот как я могу защитить цикл сообщений в приложении WinAPI:
__try {
while (GetMessage(&msg, NULL, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER){
::MessageBox(NULL, _T("FATAL"), _T("MAIN"), MB_OK | MB_ICONERROR);
}
Таким образом, я вижу свое собственное окно сообщения, но больше ничего, и если я комментирую свое окно сообщения, приложение молча закрывается.
Но … так как сообщение, которое вы показываете, не является оригинальным Windows, я подозреваю, что у сборщика C ++ уже есть такой обработчик исключений в его цикле сообщений.
Надеюсь, поможет …