Как закончить программу на C++ после ошибки?
Я рефакторинг старого кода, и одна из вещей, которую я хотел бы рассмотреть, - это способ обработки ошибок. Я хорошо знаю исключения и то, как они работают, но я не совсем уверен, что они являются лучшим решением для ситуаций, с которыми я пытаюсь справиться.
в этом коде, если вещи не проверяются, на самом деле нет причин или преимуществ для размотки стека. Мы закончили. Нет смысла пытаться спасти корабль, потому что это неинтерактивный код, который работает параллельно через двигатель Солнечной решетки. Пользователь не может вмешиваться. Более того, эти ошибки не представляют исключительные обстоятельства. Их ждут.
Итак, как мне лучше бороться с этим? Одна вещь, которую я не уверен, что хочу, - это точка выхода в каждом методе класса, который может потерпеть неудачу. Это кажется unmaintainable. Я ошибаюсь? Это приемлемая практика, чтобы просто позвонить exit()
или abort()
в точке отказа в таких кодах? Или я должен отбросить исключение на всем пути назад к некоторым общий оператор catch в main? В чем преимущество?
4 ответов
выбрасывание исключения, которое будет поймано в main, а затем выход, означает, что ваши объекты ресурсов RAII очищаются. На большинстве систем это не требуется для многих типов ресурсов. ОС будет очищать память, дескрипторы файлов и т. д. (хотя я использовал систему, где неспособность освободить память означала, что она оставалась выделенной до перезапуска системы, поэтому утечка при выходе из программы не была хорошей идеей.)
но есть другие типы ресурсов, которые вы можете захотеть освободить чисто, такие как сеть или соединения с базой данных или механическое устройство, которое вы управляете, и его необходимо безопасно отключить. Если приложение использует много таких вещей, вы можете предпочесть выбросить исключение, чтобы размотать стек обратно в main, а затем выйти.
таким образом, соответствующий метод выхода зависит от приложения. Если приложение знает, что это безопасно, вызов _Exit(), abort(), exit() или quickexit () может быть вполне разумным. (Код библиотеки не должен вызывать их, так как, очевидно, библиотека не имеет идея ли его безопасно для каждого приложения, которое когда-либо будет использовать библиотеку.) Если есть какая-то критическая очистка, которая должна быть выполнена до выхода приложения, но вы знаете, что она ограничена, то приложение может зарегистрировать этот код очистки через atexit() или at_quick_exit().
поэтому в основном решите, что вам нужно очистить, документировать его, реализовать и попытаться убедиться, что он протестирован.
приемлемо завершить программу, если она не может обрабатывать ошибку изящно. Есть несколько вещей, которые вы можете сделать:
- вызов
abort()
если вам нужен дамп памяти. - вызов
exit()
если вы хотите дать возможность запустить эти процедуры, зарегистрированные сatexit()
(это, скорее всего, вызовет деструкторы для глобальных объектов c++). - вызов
_exit()
завершить процесс немедленно.
нет ничего плохого в использовании этих функций до тех пор, пока вы понимаете, что делаете, знаете свои другие варианты и добровольно выбираете этот путь. В конце концов, именно поэтому эти функции существуют. Поэтому, если вы не считаете, что имеет смысл пытаться справиться с ошибкой или сделать что - то еще, когда это произойдет-продолжайте. Что я, вероятно, сделаю, это попытаюсь зарегистрировать какое-то информативное сообщение (скажем, в syslog) и вызвать _exit
. Если ведение журнала не удается-вызовите abort
получить ядро вдоль окончания.
Я бы предложил вызвать глобальную функцию
void stopProgram() {
exit(1);
}
позже вы можете изменить его поведение, поэтому он ремонтопригоден.
как вы указали, имея exit
или abort
разбросанный по всему вашему коду не поддерживается ... кроме того, в будущем может быть механизм, который позволит вам восстановить ошибку или обработать ошибку более изящным образом, чем просто выйти, и если вы уже жестко закодировали эту функциональность, то ее будет очень трудно отменить.
бросая исключение, которое поймано в main()
это ваш лучший выбор на данный момент, который также даст вам гибкость в будущем следует запускать код по другому сценарию, который позволит вам восстанавливаться от ошибок или обрабатывать их по-другому. Кроме того, исключение может помочь, если вы решите добавить больше поддержки отладки и т. д., так как это даст вам пятна для реализации функций ведения журнала и записи состояния программы из изолированных и ремонтопригодных точек в программном обеспечении, прежде чем вы решите позволить программе выйти.