В C может ли функция exit() или она должна позволять main() обрабатывать это?

Я пишу программу на C, и мне кое-что интересно. В программе есть несколько функций, которые возвращают 1 в случае успеха и 0 в случае неудачи, и большинство из них вызывается main() (хотя некоторые вызываются другими функциями). Это для задания, и если будет обнаружена ошибка, мне нужно напечатать ошибку в stderr, используя fprintf(), и завершить программу.

Каков правильный способ обработки завершения ошибки? Должен ли я разрешить функции печатать в stderr, затем вернуть 1 обратно в main(), а затем заставить main() фактически завершиться, или функция должна сама обрабатывать печать ошибок и завершение программы?


person vaindil    schedule 15.02.2015    source источник


Ответы (2)


Стандарт C гласит:

5.1.2.2.3 Если возвращаемый тип функции main является типом, совместимым с int, возврат из начального вызова функции main эквивалентен вызову функции выхода со значением, возвращаемым основной функцией в качестве аргумента.

Таким образом, совершенно верно, когда вы сталкиваетесь с фатальной ошибкой, чтобы сделать exit(errcode);

Полезно знать: с atexit() вы можете указать функцию (без аргументов), которая будет вызываться exit() (например, чтобы убрать беспорядок). Можно даже определить несколько таких функций: они будут вызываться в порядке, обратном их регистрации.

person Christophe    schedule 15.02.2015
comment
В зависимости от типа обнаруженной фатальной ошибки exit может быть нецелесообразно. Есть причина для _Exit (или abort). - person Deduplicator; 16.02.2015
comment
Идеально, именно то, что я искал. Спасибо! - person vaindil; 16.02.2015
comment
@Deduplicator, ты, конечно, прав. Мой ответ был о возвращении из main() против exit(). Конечно, в исключительных случаях можно было бы порекомендовать abort() или _Exit(), но я бы сказал, что это скорее исключение, чем правило. - person Christophe; 16.02.2015

Это зависит от ваших потребностей. Если произойдет катастрофическая ошибка, и вам нужно срочно выйти, вы можете позвонить exit(). Вы можете думать об этом как о «паническом броске».

Но хороший тон требует, чтобы вы никогда не exit(), а вместо этого возвращались из всех вызовов функций и позволяли main() возвращаться. На самом деле хорошим тоном будет делать это, даже если возникает ошибка, если это возможно. exit() предназначен для использования только в редких ситуациях, когда вы специально хотите предотвратить выполнение любого другого кода.

Рассмотрим, например, что произойдет, если ваш преподаватель захочет включить функции, написанные каждым студентом, в большую программу и вызывать их одну за другой. Если одна из функций завершится, оставшиеся функции учащихся никогда не запустятся.

person Mike Nakis    schedule 15.02.2015
comment
Не путайте exit (который вызывает atexit-обработчики) с _Exit. - person Deduplicator; 16.02.2015
comment
Функция exit() выполняет корректное завершение работы, закрывая потоки ввода-вывода и очищая ожидающие выходные данные, а также запуская функции, зарегистрированные с помощью atexit(). abort() не обязательно сбрасывает любой ожидающий вывод из стандартных потоков ввода-вывода и не запускает никаких функций, зарегистрированных с помощью atexit(), и обычно создает дамп ядра (как если бы процесс был завершен сигналом SIGABRT). Есть также функции _exit() и _Exit(). В C11 также есть функция quick_exit() и соответствующая функция at_quick_exit(). - person Jonathan Leffler; 16.02.2015
comment
@JonathanLeffler спасибо за информацию, я вижу, что это слишком сложно и, вероятно, не представляет интереса для ОП, поэтому я просто удалю часть о abort() из своего ответа, чтобы все было просто. - person Mike Nakis; 16.02.2015
comment
Я не припомню, чтобы когда-либо видел, как exit() называл панический выход до прочтения этого ответа. - person Jonathan Leffler; 16.02.2015
comment
@JonathanLeffler, это не неслыханно (stackoverflow.com/questions/2177597/) либо на C, либо на других языках (github.com/pingviini/mydotfiles/blob/master/install.sh), но в любом случае я переформулирую. - person Mike Nakis; 16.02.2015
comment
В ПОРЯДКЕ; вот почему я сказал, что не помню, чтобы когда-либо видел, подчеркивая мою личную ограниченность… Я думаю, что это необычное название — это совершенно обычный способ завершения программы. Операции «панического выхода» — это такие вещи, как _exit() и abort() в моей книге. […просматривая вашу внешнюю ссылку…] Автор кода создал там функцию с именем panic(), которая выдает сообщение об ошибке, а затем вызывает exit(). Паника в уме автора функции; exit() все еще совершенно нормально. Паника также имеет особое значение, например, в контексте ядер Unix (и Linux). - person Jonathan Leffler; 16.02.2015
comment
Возврат к main() не обязательно является единственной хорошей формой, иначе в стандарте не было бы написано, что оба эквивалентны. Термин «хорошая форма» относится к личному мнению. Мой личный опыт показывает, что для редких и очень вложенных ошибок иногда более эффективно иметь твердый exit(), чем разрабатывать сложный многоуровневый возврат ошибок. Но эти мысли остаются мнениями, а не фактами. - person Christophe; 16.02.2015