На самом деле, это различие, но это тонкое. Это имеет больше последствий для C ++, но различия важны.
Когда я звоню return
в main()
, деструкторы будут вызываться для моих локально контекстных объектов. Если я позвоню exit()
, никакой деструктор не будет вызван для моих локально ограниченных объектов! Перечитайте это. exit()
не возвращается . Это означает, что, как только я это называю, «нет бэкси». Любые объекты, которые вы создали в этой функции, не будут уничтожены. Часто это не имеет значения, но иногда это имеет место, например закрытие файлов (конечно, вы хотите, чтобы все ваши данные были записаны на диск?).
Обратите внимание, что static
объекты будут очищены, даже если вы позвоните exit()
. Наконец, обратите внимание, что если вы используете abort()
, ни один объект не будет уничтожен. То есть никакие глобальные объекты, никакие статические объекты и никакие локальные объекты не будут вызывать свои деструкторы.
Действуйте с осторожностью, предпочитая выход, а не возврат.
http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
Свободная память
источник
thread_local
будут называться деструкторы объектов. Деструкторы для других локальных объектов до сих пор не вызваны. ideone.com/Y6Dh3fexit()
чистым закрытием файлов на самом деле является неправильной. Единственное время, когда данные не могут быть сброшены, находится в противоположном случае: то есть, если вы используетеreturn
frommain()
и один вызвалsetbuf()
илиsetvbuf()
с буфером, объявленным как автоматическое хранение вmain()
(как обсуждено в ответе R. ниже). Очень плохо, что этот вопрос помечен как C, так и C ++ (и стиль кодирования - это не проблема стиля!).Еще одно отличие:
exit
это функция стандартной библиотеки, поэтому вам нужно включить заголовки и ссылку на стандартную библиотеку. Чтобы проиллюстрировать (на C ++), это допустимая программа:но для использования
exit
вам понадобится включить:Плюс к этому добавляется дополнительное предположение: у вызова
exit
frommain
те же побочные эффекты, что и при возврате нуля. Как уже отмечали другие, это зависит от того, какой исполняемый файл вы создаете (то есть, кто вызываетmain
). Вы кодируете приложение, которое использует C-runtime? Плагин майя? Служба Windows? Водитель? Каждый случай потребует исследования, чтобы увидеть, еслиexit
эквивалентноreturn
. Использование IMHO,exit
когда вы действительно имеете в виду,return
просто делает код более запутанным. OTOH, если вы действительно имеете в видуexit
, то во что бы то ни стало используйте его.источник
Существует по крайней мере одна причина для предпочтения
exit
: если какой-либо из вашихatexit
обработчиков ссылается на данные продолжительности автоматического храненияmain
или если вы использовалиsetvbuf
илиsetbuf
для назначения одному из стандартных потоков буфер буферизации автоматического храненияmain
, то возвращение изmain
производит неопределенное поведение, но вызовexit
действителен.Другое потенциальное использование (обычно зарезервированное для игрушечных программ) - выход из программы с рекурсивными вызовами
main
.источник
main()
- это просто функция, как и любая другая. С другой стороны, поскольку он имеет особое упоминание в стандарте, стандарт должен быть достаточно осторожным в отношении того, как он определяетmain()
и что ему близко и дорого. Однако, в конце концов, хотя стандарт не требует (и не должен ) компиляторов делать что-то особенное с автоматическим хранением вmain()
. Пожалуйста, внимательно прочитайте сноску № 11 под абзацем, на который вы ссылались в своем комментарии.Я всегда использую,
return
потому что стандартный прототип дляmain()
говорит, что он возвращаетint
.Тем не менее, некоторые версии стандартов предоставляют
main
особый режим и предполагают, что он возвращает 0, если нет явногоreturn
утверждения. Учитывая следующий код:G ++ только генерирует предупреждение
foo()
и игнорирует пропущенный возврат изmain
:источник
return
для завершения ее выполнения. Вызовexit()
также является допустимым, а иногда и необходимым, способом прекращения выполнения любой функции. На самом деле, как я и другие описывали в другом месте, вызовexit()
даже отmain()
передает гораздо более четкое намерение выйти из всего процесса, сохраняет автоматическое хранение до завершения процесса и облегчает обслуживание во время будущего рефакторинга кода. Таким образом, использование Creturn
вmain()
случае, когда целью является завершение процесса, возможно, является плохой практикой.Я НАСТОЯТЕЛЬНО поддерживаю комментарий Р. об использовании exit (), чтобы избежать автоматического сохранения в памяти
main()
до того, как программа действительно завершится.return X;
Заявление вmain()
не точно эквивалентно вызовуexit(X);
, так как динамическое хранениеmain()
исчезает , когдаmain()
возвращается, но он не обращается в нуль , если вызовexit()
сделан вместо этого.Кроме того, в C или любом C-подобном языке
return
оператор настоятельно намекает читателю, что выполнение будет продолжаться в вызывающей функции, и хотя это продолжение выполнения обычно технически верно, если вы считаете подпрограмму запуска C, которая вызвала вашуmain()
функцию, это не так. именно то, что вы имеете в виду, когда вы хотите закончить процесс.В конце концов, если вы хотите завершить свою программу из любой другой функции, кроме как
main()
вы должны вызватьexit()
. Кроме того, последовательное выполнение этогоmain()
делает ваш код намного более читабельным, а также значительно упрощает повторный анализ вашего кода; т. е. код, скопированный изmain()
какой-либо другой функции, не будет работать неправильно из-за случайныхreturn
операторов, которые должны были бытьexit()
вызовами.Таким образом, объединяя все эти пункты вместе, можно сделать вывод, что это плохая привычка , по крайней мере для C, использовать
return
оператор для завершения программыmain()
.источник
exit()
вообще избегать , но используйте его, если альтернативы athrow
илиabort()
не работают в определенном контексте. Но особенно избегайтеexit()
main и используйте return в main вместо обычной практики.Некоторые компиляторы для необычных платформ
exit()
могут преобразовать свой аргумент в значение выхода вашей программы, в то время как возвращение изmain()
может просто передать значение непосредственно в среду хоста без какого-либо перевода.Стандарт требует идентичного поведения в этих случаях (в частности, он говорит, что возвращение чего-либо, из-
int
совместимогоmain()
должно быть эквивалентно вызовуexit()
с этим значением). Проблема в том, что разные ОС имеют разные соглашения для интерпретации выходных значений. Во многих (МНОГО!) Системах 0 означает успех, а все остальное - неудача. Но, скажем, в VMS нечетные значения означают успех, а четные - неудачу. Если вы вернули 0 изmain()
, пользователь VMS увидит неприятное сообщение о нарушении доступа. На самом деле не было нарушения прав доступа - это было просто стандартное сообщение, связанное с кодом ошибки 0.Затем появился ANSI и благословил,
EXIT_SUCCESS
и вEXIT_FAILURE
качестве аргументов вы могли бы передатьexit()
. Стандарт также говорит, чтоexit(0)
должен вести себя идентичноexit(EXIT_SUCCESS)
, так что большинство реализаций определяютEXIT_SUCCESS
его0
.Поэтому стандарт ставит вас в тупик в VMS, поскольку не оставляет стандартного способа вернуть код ошибки, который имеет значение 0.
Поэтому компилятор VAX / VMS C начала 1990-х годов не интерпретировал возвращаемое значение
main()
, а просто возвращал любое значение в среду хоста. Но если бы вы использовалиexit()
его, он сделал бы то, что требовал стандарт: преобразовалEXIT_SUCCESS
(или0
) в код успеха иEXIT_FAILURE
в общий код ошибки. Чтобы использоватьEXIT_SUCCESS
, вы должны были передать егоexit()
, вы не могли вернуть егоmain()
. Я не знаю, сохранили ли такое поведение более современные версии этого компилятора.Портативная программа на Си раньше выглядела так:
В стороне: Если я правильно помню, соглашение VMS для значений выхода более нюанс, чем нечетное / четное. На самом деле он использует что-то вроде младших трех битов для кодирования уровня серьезности. В целом, однако, уровни нечетной серьезности указывают на успех или различную информацию, а четные указывают на ошибки.
источник
returned
по -main
разному от значения , переданногоexit
- но стандарт в частности , говорится : «Если тип возвращаемого значенияmain
функции типа совместимы сint
, возвращение из первоначального вызова вmain
функции эквивалентно вызовуexit
функции со значением, возвращаемымmain
функцией в качестве аргумента ". Это С11; C89 / C90 была почти такая же формулировка.EXIT_SUCCESS
и не было никакого способа вернуть специфичный для платформы статус ошибки со значением 0, возможно, поэтому некоторые из компиляторов эпохи рассматривали возврат из основного и поexit()
разному.В С возврат из
main
точно такой же, как вызовexit
с тем же значением.Раздел 5.1.2.2.3 стандарта C гласит:
Правила для C ++ немного отличаются, как упомянуто в других ответах.
источник
На самом деле есть разница между
exit(0)
иreturn(0)
вmain
- когда вашаmain
функция вызывается несколько раз.Следующая программа
Беги как
Результатом будет следующий вывод:
Однако этот:
Не буду ничего печатать независимо от аргументов.
Если вы уверены, что никто никогда не позвонит вам
main
явно, технически это не будет большой разницей в целом, но поддержание более ясного кодаexit
будет выглядеть намного лучше. Если вы по какой-то причине хотите позвонитьmain
- вам следует настроить его под свои нужды.Говоря о С.
источник