Soll ich EXIT_SUCCESS oder 0 von main () zurückgeben?


124

Es ist eine einfache Frage, aber ich sehe immer wieder widersprüchliche Antworten: Sollte die Hauptroutine eines C ++ - Programms zurückkehren 0oder EXIT_SUCCESS?

#include <cstdlib>
int main(){return EXIT_SUCCESS;}

oder

int main(){return 0;}

Sind sie genau dasselbe? Sollte EXIT_SUCCESSnur mit verwendet werden exit()?

Ich dachte, es EXIT_SUCCESSwäre eine bessere Option, da andere Software Null als Fehler betrachten möchte, aber ich habe auch gehört, dass 0der Compiler bei einer Rückkehr ohnehin in der Lage ist, ihn auf einen anderen Wert zu ändern.



2
Diese Antwort zu C90 umschreibt den Standard - 0und EXIT_SUCCESSwird beide als Erfolg interpretiert.
ta.speot.is

Ich werde hier antworten, da ich glaube, dass jemand anderes dies in Zukunft lesen wird. Grundsätzlich gibt es viele Paradigmen, wie "korrektes C" aussieht. Einige Paradigmen bevorzugen die Verwendung von Literalen gegenüber Makros. Anstatt beispielsweise NULL als Argument zu übergeben, übergeben sie möglicherweise (const char *) 0, um anzuzeigen, dass es sich nicht nur um eine Null handelt, sondern wenn es keine Null ist, sollte es eine sein konstanter Zeichenzeiger. Andere Paradigmen bevorzugen es, typunabhängig zu sein, und durch die Verwendung von Makrotypen können sie vermeiden, dass sie ihre Codebasis ändern müssen, wenn sich die Dinge radikal ändern. Zum Beispiel viele -
Dmitry

@Dmitry <Fortsetzung> Windows-API-Typdefinitionen sind auf neueren Plattformen nicht korrekt. Da es sich jedoch um Makros handelte, konnten sie auf einfache Weise alle Typen in diejenigen ändern, die durch Neudefinition des Makros funktionieren, und viele dieser Typen wurden einfach per Definition skaliert (zB int ist auf verschiedenen Plattformen unterschiedlich). Um es zusammenzufassen, verwenden Sie Dinge wie EXIT_SUCCESS, wenn der Rückkehrcode wichtig ist und sich in Zukunft ändern kann. Andernfalls scheint die Rückgabe von 0 eine magische Zahl zu sein, aber das ist immer noch eine vollkommen gültige Standardkonvention. Fehlercode ist meistens für Programme, um Nummernergebnisse von einem zum anderen
Dmitry

@Dmitry <Fortsetzung> Die Verwendung von Fehlercodes zum Debuggen Ihres Programms ist etwas schwach, da es, wenn es 0 zurückgibt, ziemlich nutzlose Informationen sind, außer in einigen Fällen, wenn in einem Programm nicht behandelte nicht behandelte Fehler auftreten, die dazu führen können, dass das Programm stillschweigend unterbrochen wird und Sie dies benötigen um zu überprüfen, ob es normal zurückgegeben wurde (0) oder ein stiller Fehler aufgetreten ist. Die Nummernrückgabe ist nützlicher, um 0..255 basierend auf ihren Eingaben von einem Programm zu einem anderen zu leiten. Andernfalls gibt es keinen Grund, darüber nachzudenken: Geben Sie entweder 0 zurück oder verwenden Sie eine vorkompilierte Hauptleitung, die einen ungültigen "init" -Aufruf nicht visuell einfügt ärgern Sie mit nutzloser Rückkehr.
Dmitry

Antworten:


150

EXIT_FAILURE, entweder in einer return-Anweisung in mainoder als Argument für exit(), ist die einzige tragbare Methode, um einen Fehler in einem C- oder C ++ - Programm anzuzeigen. exit(1)kann beispielsweise tatsächlich eine erfolgreiche Beendigung auf VMS signalisieren.

Wenn Sie verwenden, EXIT_FAILUREwenn Ihr Programm fehlschlägt, können Sie es auch verwenden, EXIT_SUCCESSwenn es erfolgreich ist, nur aus Gründen der Symmetrie.

Wenn das Programm jedoch niemals einen Fehler signalisiert, können Sie entweder 0oder verwenden EXIT_SUCCESS. Beide werden vom Standard garantiert, um einen erfolgreichen Abschluss zu signalisieren. (Es ist kaum möglich, EXIT_SUCCESSdass ein anderer Wert als 0 vorliegt, aber er ist bei jeder Implementierung, von der ich je gehört habe, gleich 0.)

Die Verwendung 0hat den kleinen Vorteil, dass Sie sie nicht #include <stdlib.h>in C oder #include <cstdlib>C ++ benötigen (wenn Sie eine returnAnweisung verwenden, anstatt sie aufzurufen exit()) - aber für ein Programm von erheblicher Größe werden Sie stdlib direkt oder indirekt einschließen wie auch immer.

In C, beginnend mit dem Standard von 1999, und in allen Versionen von C ++ ist das Erreichen des Endes ohnehin main()implizit return 0;, sodass Sie möglicherweise weder explizit 0noch EXIT_SUCCESSexplizit verwenden müssen. (Aber zumindest in C halte ich einen expliziten return 0;für einen besseren Stil.)

(Jemand fragte nach OpenVMS. Ich habe es nicht in einer langen Zeit verwendet, aber wie ich ungeradee Statuswerte im Allgemeinen bezeichnet Erfolg erinnern , während sogar Werte Scheitern bezeichnen. Die C Implementierung abbildet 0zu 1, so dass return 0;zeigt die erfolgreiche Beendigung. Andere Werte sind unverändert weitergegeben , zeigt also return 1;auch eine erfolgreiche Beendigung an. EXIT_FAILUREhätte einen geraden Wert ungleich Null.)


@KeithThompson Könnten Sie Ihre Antwort in Bezug auf VMS (OpenVMS?) Klarstellen. Es ist nicht klar, welche Beziehung EXIT_SUCCESS / EXIT_FAILURE mit 0 und 1 besteht. Ich würde stattdessen ungerade / gerade Werte erklären.
Malat

@malat: Benutzt du tatsächlich VMS?
Keith Thompson

Nein, ich habe es nie benutzt. Ich suchte nach einer kanonischen Antwort, da Wikipedia einen anderen Wortlaut verwendete .
Malat

1
@ Rhymoid: Dies wird durch C angegeben, nicht durch POSIX.
Keith Thompson

1
@DeanP: 0und EXIT_SUCCESSes wird nicht garantiert, dass sie denselben Wert haben (das habe ich in meiner Antwort erwähnt), aber beide bedeuten eine erfolgreiche Beendigung. EXIT_SUCCESSist stilistisch besser, wenn Sie auch verwenden EXIT_FAILURE, ist aber exit(0)in Ordnung.
Keith Thompson

25

Das ist egal. Beide sind gleich.

C ++ Standard Quotes:

Wenn der Statuswert Null oder EXIT_SUCCESS ist, wird eine implementierungsdefinierte Form der erfolgreichen Statusbeendigung zurückgegeben.


12
Für den Compiler spielt es keine Rolle, aber es kann eine Frage des Stils sein.
Celtschk

2
@celtschk: Stilfrage ist wahrnehmungsbasiert, auch bekannt als Non Standardized, so dass dies keinen Unterschied darstellt. Sie können nur Äpfel mit Äpfeln vergleichen, nicht Äpfel mit Birnen.
Alok Save

3
Es gibt keine Garantie dafür EXIT_SUCCESS == 0. Auf der anderen Seite gibt es keinen guten Grund dafür, es nicht zu sein.
Keith Thompson

@KeithThompson: Warum gibt es keine Garantie dafür, dass EXIT_SUCCESS == 0.? Bitte erklären Sie es klarer.
Zerstörer

2
@PravasiMeet: Ein System kann mehr als einen Wert haben, der den Erfolg anzeigt.
Keith Thompson

11

0 ist per Definition eine magische Zahl. EXIT_SUCCESS ist glücklicherweise fast überall gleich 0. Warum also nicht einfach 0 zurückgeben / beenden?

exit (EXIT_SUCCESS); ist reichlich klar in der Bedeutung.

Ausfahrt (0); Auf der anderen Seite ist in gewisser Weise nicht intuitiv. Jemand, der mit dem Verhalten der Shell nicht vertraut ist, könnte annehmen, dass 0 == false == schlecht ist, genau wie jede andere Verwendung von 0 in C. Aber nein - in diesem einen speziellen Fall ist 0 == Erfolg == gut. Für die meisten erfahrenen Entwickler wird dies kein Problem sein. Aber warum sollte man den neuen Mann ohne Grund stolpern?

tl; dr - Wenn es eine definierte Konstante für Ihre magische Zahl gibt, gibt es fast nie einen Grund, die Konstante überhaupt nicht zu verwenden. Es ist durchsuchbarer, oft klarer usw. und kostet Sie nichts.


Ich denke, Ihre Kommentare zu Leuten, die erwarten, dass 0 automatisch schlecht ist, sind falsch. Sehr viele APIs verwenden 0 für den Erfolg und Nicht-0 für den Fehler, selbst in der stdlib. ZB stdlib ( fclose(), setvbuf(), ...), POSIX ( listen(), pthread_create(), pipe(), ...), und viele, viele andere Bibliotheken (zB OpenGL [ glGetError()], zlib [ deflate()/ inflate()/ ...] SDL [ SDL_CreateWindowAndRenderer()/ ...], und Mehr).
Tim

2
Sicher, es gibt andere Fälle, in denen 0 für "Erfolg" verwendet wird, aber er hat Recht damit, dass es verwirrend ist.
Paul Wintz

10

Dies ist eine unendliche Geschichte, die die Grenzen (ein Mythos) der "Interoperabilität und Portabilität über alle" widerspiegelt.

Was das Programm zurückgeben sollte, um "Erfolg" anzuzeigen, sollte dadurch definiert werden, wer den Wert erhält (das Betriebssystem oder der Prozess, der das Programm aufgerufen hat), nicht durch eine Sprachspezifikation.

Aber Programmierer schreiben Code gerne auf "tragbare Weise" und erfinden daher ihr eigenes Modell für das Konzept des "Betriebssystems", das symbolische Werte definiert, die zurückgegeben werden sollen.

In einem Viele-zu-Viele-Szenario (in dem viele Sprachen dazu dienen, Programme auf viele Systeme zu schreiben) sollte nun die Entsprechung zwischen der Sprachkonvention für "Erfolg" und dem Betriebssystem (das niemand gewähren kann, immer gleich zu sein) erfolgen durch die spezifische Implementierung einer Bibliothek für eine bestimmte Zielplattform behandelt werden.

Leider war dieses Konzept zum Zeitpunkt der Bereitstellung der C-Sprache nicht so klar (hauptsächlich zum Schreiben des UNIX-Kernels), und Gigagramme von Büchern wurden mit den Worten "return 0 bedeutet Erfolg" geschrieben, da dies auf dem Betriebssystem unter zutraf diesmal mit einem C-Compiler.

Von da an wurde keine klare Standardisierung vorgenommen, wie eine solche Korrespondenz behandelt werden sollte. C und C ++ haben ihre eigene Definition von "Rückgabewerten", aber niemand gewährt eine ordnungsgemäße Betriebssystemübersetzung (oder besser: Keine Compiler-Dokumentation sagt etwas darüber aus). 0 bedeutet Erfolg, wenn dies für UNIX - LINUX und - aus unabhängigen Gründen - auch für Windows zutrifft, und dies deckt 90% der vorhandenen "Consumer-Computer" ab, die - in den meisten Fällen - den Rückgabewert ignorieren (so können wir) Diskutiere seit Jahrzehnten, aber niemand wird es jemals bemerken!)

Stellen Sie in diesem Szenario vor einer Entscheidung die folgenden Fragen: - Bin ich daran interessiert, meinem Anrufer etwas über meine bestehende Situation mitzuteilen? (Wenn ich nur immer 0 zurückgebe ... gibt es keinen Hinweis hinter dem Alles) - Hat mein Anrufer Konventionen bezüglich dieser Kommunikation? (Beachten Sie, dass ein einzelner Wert keine Konvention ist: Dies erlaubt keine Darstellung von Informationen.)

Wenn beide Antworten Nein sind, besteht die gute Lösung wahrscheinlich darin, die Hauptrückgabeanweisung überhaupt nicht zu schreiben. (Und lassen Sie den Compiler entscheiden, in Bezug auf das Ziel arbeitet).

Wenn keine Konvention vorhanden ist 0 = Erfolg, erfüllen Sie die meisten Situationen (und die Verwendung von Symbolen kann problematisch sein, wenn sie eine Konvention einführen).

Wenn Konventionen vorhanden sind, stellen Sie sicher, dass symbolische Konstanten verwendet werden, die mit ihnen kohärent sind (und stellen Sie die Kohärenz der Konventionen und nicht die Wertekohärenz zwischen den Plattformen sicher).


4

Sobald Sie anfangen, Code zu schreiben, der eine Vielzahl von Exit-Status zurückgeben kann, beginnen Sie #define, alle zu schreiben . In diesem Fall EXIT_SUCCESSist es sinnvoll, keine " magische Zahl " zu sein. Dies macht Ihren Code besser lesbar, da jeder andere Exit-Code verwendet wird EXIT_SOMETHING. Wenn Sie einfach ein Programm schreiben, das zurückgegeben wird, wenn es fertig return 0ist, gültig und wahrscheinlich sogar sauberer ist, weil es darauf hindeutet, dass es keine ausgefeilte Rückkehrcodestruktur gibt.


0

Was Sie von einem Programm zurückgeben, ist nur eine Konvention.

Nein, ich kann mir keine Umstände vorstellen, unter denen "EXIT_SUCCESS" dies nicht tun würde "0" wäre.

Persönlich würde ich "0" empfehlen.

MEINER BESCHEIDENEN MEINUNG NACH...


1
Ich programmiere C ++ seit 10 Jahren und kann mich immer noch nicht erinnern, ob 0 Erfolg oder Misserfolg in Bezug auf Rückgabewerte bedeutet.
Lahjaton_j

@ Lahjaton_j Ich verstehe. Ich denke, das liegt daran, dass es nicht intuitiv ist: Es 0ist falsch und viele Funktionen kehren 0bei einem Fehler zurück / tun nichts.
Bedeutung ist


-5

Einige Compiler könnten Probleme damit verursachen - auf einem Mac C ++ - Compiler funktionierte EXIT_SUCCESS einwandfrei für mich, aber auf einem Linux C ++ - Complier musste ich cstdlib hinzufügen, damit es wusste, was EXIT_SUCCESS ist. Davon abgesehen sind sie ein und dasselbe.


Ich meinte auf einem Mac EXIT_SUCCESS funktionierte ohne cstdlib.
Beidhändig

4
Wenn EXIT_SUCCESSohne <stdlib.h>oder gearbeitet wird <cstdlib>, muss dies von einem anderen Header direkt oder indirekt definiert worden sein. In C ++ ist es üblich, dass Standardheader #includeandere Standardheader verwenden. Wenn dies fehlerfrei kompiliert wird, int main() { return EXIT_SUCCESS; }ist Ihr Compiler wahrscheinlich fehlerhaft .
Keith Thompson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.