it-swarm.com.de

return Anweisung vs exit () in main ()

Soll ich exit() oder nur return Anweisungen in main() verwenden? Persönlich bevorzuge ich die return -Anweisungen, weil ich das Gefühl habe, jede andere Funktion zu lesen, und die Ablaufsteuerung beim Lesen des Codes (meiner Meinung nach) reibungslos ist. Und selbst wenn ich die Funktion main() umgestalten möchte, scheint return eine bessere Wahl zu sein als exit().

Tut exit() etwas Besonderes, das return nicht tut?

186
Srikanth

Eigentlich gibt es ist einen Unterschied, aber es ist subtil. Es hat mehr Auswirkungen auf C++, aber die Unterschiede sind wichtig.

Wenn ich return in main() aufrufe, werden Destruktoren für meine Objekte mit lokalem Gültigkeitsbereich aufgerufen. Wenn ich exit() aufrufe, , wird kein Destruktor für meine Objekte mit lokalem Gültigkeitsbereich aufgerufen! Lesen Sie das noch einmal durch. exit() gibt nicht zurück. Das heißt, wenn ich es einmal nenne, gibt es "keine Backsies". Alle Objekte, die Sie in dieser Funktion erstellt haben, werden nicht zerstört. Oft hat dies keine Auswirkungen, manchmal jedoch, wie das Schließen von Dateien (möchten Sie sicher, dass alle Ihre Daten auf die Festplatte geschrieben werden?).

Beachten Sie, dass static Objekte bereinigt werden, auch wenn Sie exit() aufrufen. Beachten Sie abschließend, dass bei Verwendung von abort() keine Objekte zerstört werden. Das heißt, es werden keine globalen Objekte, keine statischen Objekte und keine lokalen Objekte mit ihren Destruktoren aufgerufen.

Gehen Sie vorsichtig vor, wenn Sie den Ausstieg der Rückkehr vorziehen.

http://groups.google.com/group/gnu.gcc.help/msg/8348c50030cfd15a

267
FreeMemory

Ein weiterer Unterschied: exit ist eine Standardbibliotheksfunktion, daher müssen Sie Header einschließen und eine Verknüpfung mit der Standardbibliothek herstellen. Zur Veranschaulichung (in C++) ist dies ein gültiges Programm:

int main() { return 0; }

aber um exit zu verwenden, benötigen Sie ein Include:

#include <stdlib.h>
int main() { exit(EXIT_SUCCESS); }

Hinzu kommt die zusätzliche Annahme, dass das Aufrufen von exit aus main die gleichen Nebenwirkungen hat wie das Zurückgeben von Null. Wie bereits erwähnt, hängt dies davon ab, welche Art von ausführbarer Datei Sie erstellen (d. H. Wer main aufruft). Codieren Sie eine App, die die C-Laufzeit verwendet? Ein Maya-Plugin? Ein Windows-Dienst? Ein Fahrer? In jedem Fall muss untersucht werden, ob exitreturn entspricht. IMHO mit exit, wenn Sie wirklich gemeinreturn nur macht den Code verwirrender. OTOH, wenn Sie wirklich meinenexit, dann verwenden Sie es auf jeden Fall.

24
jwfearn

Es gibt mindestens einen Grund, warum Sie exit bevorzugen sollten: Wenn einer Ihrer atexit -Handler auf Daten zur automatischen Speicherdauer in main verweist oder wenn Sie setvbuf verwendet haben ] _ oder setbuf, um einem der Standard-Streams einen Puffer für die automatische Speicherdauer in main zuzuweisen. Wenn Sie dann von main zurückkehren, wird undefiniertes Verhalten erzeugt, aber exit ist gültig.

Eine andere mögliche Verwendung (normalerweise jedoch für Spielzeugprogramme reserviert) ist das Beenden eines Programms mit rekursiven Aufrufen von main.

16
R..

Tut exit () etwas Besonderes, was return nicht tut?

Bei einigen Compilern für ungewöhnliche Plattformen übersetzt exit() das Argument möglicherweise in den Exit-Wert Ihres Programms, während eine Rückgabe von main() den Wert möglicherweise ohne Übersetzung direkt an die Host-Umgebung übergibt.

Der Standard verlangt in diesen Fällen dasselbe Verhalten (insbesondere heißt es, dass das Zurückgeben von etwas, das int- kompatibel von main() ist, gleichbedeutend mit dem Aufrufen von exit() mit diesem Wert sein sollte). Das Problem ist, dass verschiedene Betriebssysteme unterschiedliche Konventionen für die Interpretation der Exit-Werte haben. Auf vielen (VIELEN!) Systemen bedeutet 0 Erfolg und alles andere ist ein Fehler. In VMS bedeuten ungerade Werte Erfolg und gerade Misserfolge. Wenn Sie von main() 0 zurückgegeben haben, wird einem VMS-Benutzer eine unangenehme Nachricht über eine Zugriffsverletzung angezeigt. Es gab eigentlich keine Zugriffsverletzung - das war einfach die Standardnachricht, die dem Fehlercode 0 zugeordnet war.

Dann kam ANSI und segnete EXIT_SUCCESS Und EXIT_FAILURE Als Argumente, die Sie an exit() übergeben konnten. Der Standard sagt auch, dass sich exit(0) identisch mit exit(EXIT_SUCCESS) verhalten soll, daher definieren die meisten Implementierungen EXIT_SUCCESS Bis 0.

Der Standard versetzt Sie daher in eine Bindung an VMS, da es keine Standardmethode gibt, um einen Fehler - Code zurückzugeben, der zufällig den Wert 0 hat.

Der VAX/VMS C-Compiler der frühen 90er-Jahre interpretierte daher den Rückgabewert von main() nicht, sondern gab einfach einen beliebigen Wert an die Host-Umgebung zurück. Wenn Sie jedoch exit() verwenden würden, würde dies den erforderlichen Standard erfüllen: Übersetzen Sie EXIT_SUCCESS (Oder 0) In einen Erfolgscode und EXIT_FAILURE In einen allgemeinen Fehler Code. Um EXIT_SUCCESS Zu verwenden, haben Sie hatte es an exit() übergeben, Sie konnten es nicht von main() zurückgeben. Ich weiß nicht, ob modernere Versionen dieses Compilers dieses Verhalten beibehalten haben.

Ein portables C-Programm sah so aus:

#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 */
}

Nebenbei: Wenn ich mich richtig erinnere, ist die VMS-Konvention für Exit-Werte nuancierter als ungerade/gerade. Es verwendet tatsächlich so etwas wie die niedrigen drei Bits, um einen Schweregrad zu codieren. Im Allgemeinen zeigten jedoch die ungeraden Schweregrade Erfolg oder verschiedene Informationen an, und die geraden zeigten Fehler an.

5
Adrian McCarthy

I STARK zweitens der Kommentar von R. zur Verwendung von exit (), um zu vermeiden, dass die automatische Speicherung in main() zurückgefordert wird, bevor das Programm tatsächlich endet . Eine return X; - Anweisung in main() entspricht nicht genau einem Aufruf von exit(X);, da der dynamische Speicher von main() verschwindet, wenn main() zurückgegeben wird , aber es verschwindet nicht, wenn stattdessen ein Aufruf von exit() erfolgt.

Darüber hinaus weist eine return -Anweisung in C oder einer beliebigen C-ähnlichen Sprache den Leser stark darauf hin, dass die Ausführung in der aufrufenden Funktion fortgesetzt wird, und während diese Fortsetzung der Ausführung in der Regel technisch wahr ist, wenn Sie die C-Startroutine mitzählen Mit der Funktion main() meinen Sie nicht genau , wenn Sie den Prozess beenden möchten.

Wenn Sie Ihr Programm in einer anderen Funktion als main() beenden möchten, müssen Sie exit() aufrufen. Wenn Sie dies auch in main() konsequent tun, wird Ihr Code viel besser lesbar und es wird für jeden einfacher, Ihren Code neu zu faktorisieren. d.h. Code, der von main() in eine andere Funktion kopiert wurde, verhält sich nicht falsch, da zufällige return -Anweisungen exit() hätten aufrufen sollen .

Wenn Sie also alle diese Punkte zusammenfassen, ist es eine schlechte Angewohnheit , zumindest für C, eine return -Anweisung zu verwenden, um das Programm in main().

5
Greg A. Woods

Ich benutze immer return, weil der Standardprototyp für main() besagt, dass er ein int zurückgibt.

Das heißt, einige Versionen der Standards geben main eine Sonderbehandlung und gehen davon aus, dass sie 0 zurückgeben, wenn es keine explizite return -Anweisung gibt. Mit folgendem Code:

int foo() {}
int main(int argc, char *argv[]) {}

G ++ generiert nur eine Warnung für foo() und ignoriert die fehlende Rückgabe von main:

% g++ -Wall -c foo.cc
foo.cc: In function ‘int foo()’:
foo.cc:1: warning: control reaches end of non-void function
5
Alnitak

In C entspricht die Rückkehr von main genau dem Aufruf von exit mit demselben Wert.

Abschnitt 5.1.2.2.3 des C-Standards lautet:

Wenn der Rückgabetyp der Hauptfunktion mit int kompatibel ist, entspricht eine Rückgabe vom ersten Aufruf an die Hauptfunktion dem Aufrufen der Exit-Funktion mit dem von der Hauptfunktion zurückgegebenen Wert als sein Argument ; 11) Das Erreichen von}, das die Hauptfunktion beendet, gibt den Wert 0 zurück. Wenn der Rückgabetyp nicht mit int kompatibel ist, ist der an die Host-Umgebung zurückgegebene Beendigungsstatus nicht angegeben.

Die Regeln für C++ sind etwas anders, wie in anderen Antworten erwähnt.

0
dbush

Es gibt tatsächlich IS einen Unterschied zwischen exit(0) und return(0) in main - wenn Ihre main -Funktion mehrmals aufgerufen wird.

Das folgende Programm

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    return(0);
  printf("%d", main(argc - 1, argv));
}

Rennen wie

./program 0 0 0 0

Ergibt folgende Ausgabe:

00000

Dieser jedoch:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  if (argc == 0)
    exit(0);
  printf("%d", main(argc - 1, argv));
}

Gibt unabhängig von den Argumenten nichts aus.

Wenn Sie sicher sind, dass niemand Ihre main explizit aufrufen wird, ist dies im Allgemeinen technisch gesehen kein großer Unterschied, aber um einen klareren Code beizubehalten, würde exit viel besser aussehen. Wenn Sie aus irgendeinem Grund main aufrufen möchten, sollten Sie dies an Ihre Bedürfnisse anpassen.

Apropos C.

0
radrow