Какая разница между этими тремя, и как мне закончить программу в случае исключения, с которым я не могу нормально справиться?
Прервать, прекратить или выйти?
Ответ 1
Мой совет - не использовать никого из них. Вместо этого поймайте исключения, с которыми вы не можете справиться в main(), и просто возвращайтесь оттуда. Это означает, что вам гарантировано, что разворачивание стека происходит правильно и вызываются все деструкторы. Другими словами:
int main() {
try {
// your stuff
}
catch( ... ) {
return 1; // or whatever
}
}
Ответ 2
-
abort указывает на "ненормальный" конец программы и вызывает сигнал POSIX SIGABRT, что означает, что любой обработчик, который вы зарегистрировали для этого сигнала, будет вызван, хотя программа все равно прекратит использование слов в любом случае. Обычно вы используете
abortв программе на C, чтобы выйти из непредвиденного случая ошибки, где ошибка, вероятно, будет ошибкой в программе, а не что-то вроде плохого ввода или сбоя сети. Например, вы могли быabort, если бы была найдена структура данных с указателем NULL в ней, если это логически не произойдет. -
exit указывает на "нормальный" конец программы, хотя это может по-прежнему указывать на сбой (но не на ошибку). Другими словами, вы можете
exitс кодом ошибки, если пользователь дал ввод, который не мог быть проанализирован, или файл не мог быть прочитан. Код выхода 0 указывает на успех.exitтакже необязательно вызывает обработчики до того, как он закончит программу. Они регистрируются функциямиatexitиon_exit. -
std:: terminate - это то, что автоматически вызывается в программе на С++, когда есть необработанное исключение. Это по существу эквивалент С++ для
abort, предполагая, что вы сообщаете обо всех своих исключительных ошибках с помощью исключения исключений. Это вызывает обработчик, который устанавливается функциейstd::set_terminate, которая по умолчанию просто вызываетabort.
В С++ вы обычно хотите избежать вызова abort или exit при ошибке, так как вам лучше сбросить исключение и позволить коду дальше вверх по стеку вызовов решить, подходит ли конец программы. Независимо от того, используете ли вы exit для успеха, дело обстоятельство - имеет ли смысл закончить программу где-то иначе, чем оператор return в main.
std::terminate следует рассматривать как средство отчетности об ошибках последнего уровня, даже в С++. Проблема с std::terminate заключается в том, что обработчик terminate не имеет доступа к исключению, которое прошло необработанным, поэтому нет способа сказать, что это было. Вы обычно гораздо лучше обертываете всю основную часть в блоке try { } catch (std::exception& ex) { }. По крайней мере, вы можете сообщить больше информации об исключениях, полученных из std::exception (хотя, конечно, исключения, которые не происходят из std::exception, все равно будут обработаны без обработки).
Обтекание тела main в try { } catch(...) { } не намного лучше, чем установка обработчика завершения, потому что снова у вас нет доступа к рассматриваемому исключению. Изменить: Ответ на Нил Баттерворт: есть преимущество в том, что в этом случае стек разматывается, что (несколько удивительно) неверно для необработанного исключения.
Ответ 3
std:: abort и std:: exit (и больше: std:: _ Exit, std:: quick_exit) - это только функции нижнего уровня. Вы используете их, чтобы сообщить программе, что вы хотите, чтобы это точно: какие деструкторы (и если) вызывать, какие другие функции очистки вызывать, какое значение возвращать и т.д.
std:: terminate - это абстракция более высокого уровня: она вызывается (либо во время выполнения, либо для вас), чтобы указать, что произошла ошибка в программе, и по какой-то причине ее невозможно обработать, выбросив исключение. Необходимость в этом обычно возникает, когда ошибка возникает в самом механизме исключения, но вы можете использовать ее в любое время, когда вы не хотите, чтобы ваша программа продолжалась за пределами данной ошибки. Я собрал полный список ситуаций, когда std:: terminate называется в моем сообщении. Не указано, что делает std:: terminate, потому что вы контролируете его. Вы можете настроить поведение, зарегистрировав любые функции. Ограничения, которые у вас есть, это то, что функция не может вернуться на сайт ошибки и не может выйти из-за исключения, но технически вы даже можете запустить свой насос сообщений внутри. Список полезных вещей, которые вы можете сделать внутри, см. мой другой пост.
В частности, обратите внимание, что std:: terminate считается обработчиком исключений в контекстах, где std:: terminate вызывается из-за вызванного исключения, которое невозможно обработать, и вы можете проверить, что такое исключение, и проверить его, используя С++ 11 с использованием std:: rethrow_exception и std:: current_exception. Это все в моем сообщении.
Ответ 4
Если ваша программа многопоточная, то вызов exit(), скорее всего, приведет к сбою, потому что объекты global/static std::thread будут пытаться уничтожить, не выходя из своих потоков.
Если вы хотите вернуть код ошибки и выйти из программы (более или менее), вызовите quick_exit() в многопоточных программах.
Для аномального завершения (без возможности указать код ошибки) можно вызвать abort() или std::terminate().
Примечание: quick_exit() не поддерживается MSVС++ до версии 2015.
Ответ 5
-
terminate() автоматически вызывается когда возникает исключение, которое не может обрабатываться. По умолчанию terminate() вызывает abort(). Вы можете настроить дескриптор с функцией set_terminate().
abort() отправляет сигнал SIGABRT.
exit() не обязательно является плохим вещь. Он успешно завершает приложение и вызовы atexit() функции в порядке LIFO. Я не обычно см. это в С++ приложений, однако, я вижу это в многие приложения на основе UNIX, где отправляет код завершения в конце. Обычно выход (0) указывает на успешный запуск приложения.
Ответ 6
- terminate оставляет возможность зарегистрировать, что произойдет, когда оно будет вызвано. Должен быть один из двух других.
- exit - это обычный выход, позволяющий указать статус выхода. Выполняются обработчики, зарегистрированные с помощью at_exit().
- abort - ненормальный выход. Единственное, что выполняется, это обработчик сигнала для SIGABRT.