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?

Author: Bugfinger, 2009-01-20

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

 286
Author: FreeMemory,
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.

 25
Author: jwfearn,
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.

 17
Author: R.. GitHub STOP HELPING ICE,
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
 5
Author: Alnitak,
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.

W związku z tym standard umieszcza cię w wiązaniu na maszynach wirtualnych, ponieważ nie pozostawia standardowego sposobu zwracania kodu , który ma wartość 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.

 5
Author: Adrian McCarthy,
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().

 4
Author: Greg A. Woods,
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.

 0
Author: dbush,
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.

 -1
Author: radrow,
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