Instrukcja return vs exit () w main()
Czy powinienem używać exit()
czy tylko return
wypowiedzi w main()
? Osobiście popieram wypowiedzi return
, ponieważ czuję, że to tak, jakby czytać jakąkolwiek inną funkcję, a kontrola przepływu podczas czytania kodu jest płynna (moim zdaniem). I nawet jeśli chcę refaktorować funkcję main()
, posiadanie return
wydaje się lepszym Wyborem niż exit()
.
Czy exit()
robi coś specjalnego, czego return
nie robi?
8 answers
Właściwie, jestjest różnica, ale jest subtelna. Ma więcej implikacji dla C++, ale różnice są ważne.
Kiedy wywołam return
W main()
, destruktory będą wywoływane dla moich lokalnie zlokalizowanych obiektów. If I call exit()
, żaden Destruktor nie będzie wywoływany dla moich lokalnie zlokalizowanych obiektów!Przeczytaj to jeszcze raz. exit()
nie zwraca . Oznacza to, że kiedy to nazywam, nie ma żadnych zwrotów."Wszelkie obiekty utworzone w tej funkcji nie będą zniszczony. Często nie ma to żadnego wpływu, ale czasami tak jest, jak zamykanie plików (na pewno chcesz, aby wszystkie dane zostały spłukane na dysk?).
Zauważ, że static
obiekty zostaną wyczyszczone, nawet jeśli wywołasz exit()
. Na koniec zauważ, że jeśli użyjesz abort()
, żadne obiekty nie zostaną zniszczone. Oznacza to, że żadne obiekty globalne, żadne obiekty statyczne i żadne lokalne nie będą miały nazwanych destruktorów.
Zachowaj ostrożność podczas faworyzowania wyjścia nad / align = "left" /
Http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-20 14:30:54
Kolejna różnica:
exit
jest standardową biblioteką
funkcja, więc musisz dołączyć
nagłówki i łącze ze standardem
biblioteka. Do zilustrowania (w C++),
to jest poprawny program:
int main() { return 0; }
Ale aby użyć exit
będziesz potrzebował include:
#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }
Plus to dodaje dodatkowe założenie: że wywołanie exit
z main
ma takie same skutki uboczne jak zwracanie zera. Jak zauważyli inni, zależy to od tego, jakiego rodzaju program wykonywalny budujesz(np. kto dzwoni main
). Są kodujesz aplikację używającą C-runtime? Wtyczka Maya? Serwis Windows? Kierowca? Każdy przypadek będzie wymagał badań, aby sprawdzić, czy {[2] } jest równoważne return
. IMHO używając exit
Kiedy naprawdę return
tylko sprawia, że kod jest bardziej mylący. OTOH, jeśli naprawdę masz na myśli exit
, więc użyj go.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-04 18:02:21
Istnieje co najmniej jeden powód, dla którego warto wybrać exit
: jeśli któryś z Twoich programów obsługi atexit
odnosi się do danych automatycznego przechowywania czasu trwania w main
, lub jeśli użyłeś setvbuf
lub setbuf
Aby przypisać do jednego ze standardowych strumieni automatyczny bufor czasu trwania w main
, to zwrócenie z main
spowoduje niezdefiniowanie zachowania, ale wywołanie exit
jest poprawne.
Innym potencjalnym zastosowaniem (Zwykle zarezerwowanym dla programów zabawkowych) jest wyjście z programu z rekurencyjnymi wywołaniami main
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-02 12:07:32
Zawsze używam return
, ponieważ standardowy prototyp main()
mówi, że zwraca int
.
To powiedziawszy, niektóre wersje standardów dają main
specjalne traktowanie i zakładają, że zwraca 0, jeśli nie ma wyraźnego return
stwierdzenia. Podano następujący kod:
int foo() {}
int main(int argc, char *argv[]) {}
G++ generuje tylko ostrzeżenie dla foo()
i ignoruje brakujący zwrot z main
:
% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-20 15:03:13
Czy exit () robi coś specjalnego, czego 'return' nie robi?
W niektórych kompilatorach dla nietypowych Platform, exit()
może przetłumaczyć swój argument na wartość końcową programu, podczas gdy powrót z main()
może po prostu przekazać wartość bezpośrednio do środowiska hosta bez tłumaczenia.
Standard wymaga w tych przypadkach identycznego zachowania (w szczególności mówi, że zwracanie czegoś, co jest int
-zgodne z main()
powinno być równoważne wywołaniu exit()
z tą wartością). Problem polega na tym, że różne systemy operacyjne mają różne konwencje interpretacji wartości wyjścia. Na wielu (MANY!) systemy, 0 oznacza sukces, a Wszystko inne jest porażką. Ale na przykład na maszynach wirtualnych dziwne wartości oznaczają sukces, a parzyste-porażkę. Jeśli zwrócisz 0 z main()
, Użytkownik maszyny wirtualnej zobaczy paskudny komunikat o naruszeniu dostępu. W rzeczywistości nie było naruszenia dostępu-to była standardowa wiadomość powiązana z kodem błędu 0.
Wtedy ANSI przyszedł razem i pobłogosławione EXIT_SUCCESS
i EXIT_FAILURE
jako argumenty, które można przekazać exit()
. Standard mówi również, że {[10] } powinien zachowywać się identycznie jak exit(EXIT_SUCCESS)
, więc większość implementacji definiuje EXIT_SUCCESS
na 0
.
Kompilator Vax/VMS c z początku lat 90. nie zinterpretował wartości zwracanej z main()
, po prostu zwrócił cokolwiek wartość dla środowiska hosta. Ale jeśli użyjesz exit()
, zrobi to, co jest wymagane standardem: Przetłumacz EXIT_SUCCESS
(lub 0
) na kod sukcesu, a EXIT_FAILURE
na ogólny kod błędu. Aby użyć EXIT_SUCCESS
, musisz przekazać go do exit()
, nie możesz go zwrócić z main()
. Nie wiem, czy bardziej nowoczesne wersje tego kompilatora zachowały to zachowanie.
Przenośny program C wyglądał tak:
#include <stdio.h>
#include <stdlib.h>
int main() {
printf("Hello, World!\n");
exit(EXIT_SUCCESS); /* to get good return value to OS */
/*NOTREACHED*/ /* to silence lint warning */
return 0; /* to silence compiler warning */
}
Na bok: o ile dobrze pamiętam, konwencja VMS dla exit wartości są bardziej niuansowane niż parzyste / nieparzyste. W rzeczywistości używa czegoś takiego jak niskie trzy bity do kodowania poziomu ważności. Ogólnie rzecz biorąc, jednak nieparzyste poziomy nasilenia wskazywały na sukces lub różne informacje, a parzyste wskazywały na błędy.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-18 20:18:55
I zdecydowanie drugi komentarz R. o używaniu exit () w celu uniknięcia automatycznego zapisu w main()
odzyskanego przed zakończeniem programu. Polecenie return X;
w main()
nie jest dokładnie równoważne wywołaniu do exit(X);
, ponieważ dynamiczne przechowywanie main()
znika, gdy main()
powraca, ale nie znika, jeśli zamiast tego zostanie wykonane wywołanie do exit()
.
Ponadto, w języku C lub dowolnym języku podobnym do C return
stwierdzenie silnie podpowiada czytelnikowi, że wykonanie kontynuuj w funkcji wywołującej i chociaż ta kontynuacja wykonania jest zwykle technicznie prawdziwa, jeśli policzysz procedurę uruchamiania C, która wywołała twoją funkcję main()
, to nie jest to dokładnie to, co masz na myśli, gdy masz na myśli zakończenie procesu.
W końcu, jeśli chcesz zakończyć swój program z poziomu innej funkcji poza main()
musisz zadzwonić. Konsekwentne działanie w main()
sprawia, że Twój kod jest o wiele bardziej czytelny, a także znacznie ułatwia kod skopiowany z main()
do innej funkcji nie będzie źle zachowywał się z powodu przypadkowych instrukcji return
, które powinny być wywołaniami exit()
.
Tak więc, łącząc wszystkie te punkty razem, wniosek jest taki, żezłym nawykiem , przynajmniej dla C, jest używanie return
instrukcji, aby zakończyć program w main()
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-06-26 21:29:57
W C zwracanie z main
jest dokładnie takie samo jak wywołanie exit
o tej samej wartości.
Sekcja 5.1.2.2.3 normy C stwierdza:
Jeśli typ zwracanej funkcji głównej jest typem zgodnym z int , powrót z początkowego wywołania do głównej funkcji jest równoważny wywołanie funkcji exit z wartością zwracaną przez main function as its argument ; 11) reaching the } that finishes the funkcja main zwraca a wartość 0. Jeśli Typ zwracanego niezgodny z int, status zakończenia powrócił do środowisko hosta jest nieokreślone.
Zasady C++ są nieco inne, jak wspomniano w innych odpowiedziach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-21 14:14:45
Istnieje różnica między exit(0)
a return(0)
w {[6] – - Gdy funkcja main
jest wywoływana wielokrotnie.
Następujący program
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
return(0);
printf("%d", main(argc - 1, argv));
}
Run as
./program 0 0 0 0
Spowoduje następujące wyjście:
00000
Jednak ten:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char** argv) {
if (argc == 0)
exit(0);
printf("%d", main(argc - 1, argv));
}
Nie wydrukuje niczego bez względu na argumenty.
Jeśli jesteś pewien, że nikt nigdy nie zadzwoni do twojego main
wyraźnie nie jest to technicznie duża różnica w ogóle, ale do utrzymania jaśniejszy kod exit
wyglądałby znacznie lepiej. Jeśli z jakiegoś powodu chcesz zadzwonić main
- powinieneś dostosować go do swoich potrzeb.
Mówiąc o C.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-23 13:35:12