ein C-Programm kann unter besonderen Umständen unter Linux nicht ausgeführt werden. Beispiel: Sie weisen Speicherplatz zu und das Betriebssystem verweigert dies.
char *buffer = (char *) malloc(1024);
if (buffer == NULL)
return ENOMEM;
Dieser Fehler wird durch den Rückgabecode gekennzeichnet, der an das Betriebssystem geliefert wird.
- Ein Rückkehrcode von 0 (EXIT_SUCCESS) wird als erfolgreiche Ausführung markiert.
- Ein Rückkehrcode, der nicht 0 ist, wird als Fehler markiert.
Also meine Frage ist, Was ist die Konvention, wenn ein Programm einen Fehler erkennt? Soll es einen positiven oder einen negativen Rückgabecode zurückgeben?
Mein Professor hat mir gesagt, dass ich unter UNIX/Linux immer einen negativen Fehlercode zurückgeben soll. Aber die errno-Codes sind alle positive ganze Zahlen. Auch das Define-Statement von EXIT_FAILURE in ist 1, eine positive Ganzzahl. Also sollte mein Code so aussehen:
char *buffer = (char *) malloc(1024);
if (buffer == NULL)
return -ENOMEM;
oder wie der obige Code? Ich weiß von Linux-Kernel-Modulen, dass sie in den meisten Fällen bei einem Fehler einen negativen Fehlercode zurückgeben.
Danke fürs Helfen.
Meine Frage ist also, wie ist die Konvention, wenn ein Programm einen Fehler erkennt. Soll es einen positiven oder einen negativen Rückgabecode zurückgeben?
Sie haben nicht den Luxus (oder die Verantwortung), diese Wahl zu treffen. Aus der Sicht von C im Allgemeinen fallen Ihre Entscheidungen in drei Kategorien:
-
Der von Ihnen angegebene Exit-Status ist entweder 0
oder EXIT_SUCCESS
(die nicht notwendigerweise verschieden sind). Dies zeigt einen erfolgreichen Abschluss an.
-
Der von Ihnen angegebene Exit-Status ist EXIT_FAILURE
. Dies zeigt einen nicht erfolgreichen Abschluss an.
-
Der von Ihnen angegebene Exit-Status ist etwas anderes.
Das an die Hostumgebung signalisierte Ergebnis lautet implementierungsdefiniert in jedem Fall, obwohl es im ersten Fall eines ist, das Erfolg kommuniziert, und im zweiten eines, das Misserfolg kommuniziert.
Jetzt auf Linux und anderen Betriebssystemen, die POSIX implementieren exit()
Semantik, die Implementierungsdefiniertheit ist standardisiert:
Der Wert des Status kann sein 0
, EXIT_SUCCESS
, EXIT_FAILURE
oder irgendein anderer Wert, obwohl nur die niederwertigsten 8 Bits (d. h. status & 0377
) ist unter erhältlich wait()
und waitpid()
;
(IEEE-Standard 1003.1-2008, Ausgabe 2016; Betonung hinzugefügt). Das ist die traditionelle UNIX-Semantik; Nur die niederwertigsten 8 Bits des von Ihnen angegebenen Ausgangsstatus sind von Bedeutung, sodass die Signiertheit verloren geht. Die aktuelle Version von POSIX sagt jedoch weiter:
der volle Wert ist ab verfügbar waitid()
und in der siginfo_t
an einen Signal-Handler für übergeben SIGCHLD
.
Also du kann teilt dem übergeordneten Prozess eine negative Zahl mit, wenn er weiß, dass er nach einer suchen muss. Im Allgemeinen wird es aber nicht gehen. Insbesondere wenn der übergeordnete Prozess die Shell ist, wird dies nicht funktionieren.
Mein Professor hat mir gesagt, dass ich unter UNIX/Linux immer einen negativen Fehlercode zurückgeben soll.
Das klingt eher nach einer Anleitung zu Funktions-Returncodes für Funktionen außer main()
aber ich verstehe nicht, warum Sie denken, dass unsere zweite Vermutung darüber, was Ihr Professor gemeint hat, zuverlässiger wäre, als Ihren Professor direkt um Klärung zu bitten.
Aber die errno-Codes sind alle positive ganze Zahlen.
Nun, eine andere Sache, die Sie mit Ihrem Professor klären sollten, wäre, ob er Ihnen spezifische Anweisungen gegeben hat, wie er erwartet, dass Sie Funktionen für seine Klasse schreiben (wahrscheinlicher), oder ob er eine Behauptung über die allgemeine C- oder POSIX-Konvention aufstellt (unwahrscheinlich, weil es viele POSIX-Funktionen gibt, auf die es nicht zutrifft) oder etwas anderes.
Beachten Sie, dass Funktionen der C-Standardbibliothek nicht zurückkehren errno
Codes. Wenn sie einen Fehlercode zurückgeben (oft, aber nicht immer, eine negative Zahl), ist der Programmierer verpflichtet, den zu konsultieren errno
Variable aus einem genauen Grund — der Rückgabecode der Funktion enthält diese Informationen im Allgemeinen nicht. Einige Funktionen sind von POSIX standardisiert, aber nicht von C tun Rückkehr errno
Codes direkt; offensichtlich folgen diese nicht dem Rezept Ihres Professors.
Beachten Sie auch das errno
Werte dienen der Kommunikation zwischen Funktionen, die von demselben Programm aufgerufen werden, nicht der Kommunikation mit der Umgebung des Programms. Sie sind nicht für die Verwendung als Programmausgangsstatus vorgesehen, und insbesondere gibt es keine Garantie dafür, dass ihre Werte in acht Bits passen (siehe oben).
Auch das Define-Statement von EXIT_FAILURE in ist 1, eine positive ganze Zahl. Also sollte mein Code so aussehen:
Der Wert von EXIT_FAILURE
ist implementierungsabhängig. Sie können daraus daher nur implementierungsspezifische Erkenntnisse gewinnen. Wie Sie jedoch sehen können, ist der allgemeine Exit-Status, der auf einen Programmfehler in Ihrer Implementierung hinweist, 1
.
Unter Linux und anderen POSIX(-ish)-Systemen erzielen Sie die beste Integration mit der Shell, indem Sie Fehlerstatus zwischen 1 und 125 wählen, da die Shell den Status 126-255 eine besondere Bedeutung zuweist und natürlich den Status 0 als Erfolg interpretiert.
char *buffer = (char *) malloc(1024);
if (buffer == NULL)
return -ENOMEM;
oder wie der obige Code? Ich weiß von Linux-Kernel-Modulen, dass sie in den meisten Fällen bei einem Fehler einen negativen Fehlercode zurückgeben.
Wieder nein. Errno-Codes sind nicht als Programmbeendigungscodes gedacht, und nur unter ganz besonderen Umständen sollten Sie versuchen, das Programm mit einem negativen Status zu beenden. Eine gängige Konvention besteht darin, eine informative Fehlermeldung zu schreiben stderr
(perror()
dient genau diesem Zweck) und dann mit Status 1 beenden oder (besser, IMO) EXIT_FAILURE
.
Wenn Sie Beendigungscodes bereitstellen möchten, die die Art des Fehlers beschreiben, müssen Sie deren Werte und Bedeutung pro Programm definieren, wobei Sie daran denken müssen, dass Sie für die beste Kompatibilität nur 1 – 125 zum Arbeiten haben.
Die Konvention für einen nicht weiter spezifizierten Fehlercode aus Ihrem Programm ist zu verwenden EXIT_FAILURE
. Er wird auf einen Wert definiert, den Ihr Betriebssystem als Fehler-Exit-Code erkennt.
Die Makros definiert in errno.h
sind nicht als Rückkehrcodes für Prozesse gedacht, sondern nur für Fehler während der Programmausführung. Die Standardbibliothek fügt sie in die Datei global errno
, Sie können sie auch als Rückgabecodes von Funktionen verwenden, wenn Sie möchten. Drei davon werden durch die C-Norm spezifiziert: EDOM
, EILSEQ
und ERANGE
. Viele weitere werden von POSIX spezifiziert. Verwenden Sie diese nicht als Rückkehrcodes von main()
(oder als Argument für exit()
).
Der Exit-Code unter UNIX/Linux von a Prozessdas return
Aussage ein main()
oder ein Anruf bei exit()
ist ohne Vorzeichen im Bereich 0 – 255.
Von einem Funktion es kann jeder Typ sein, den Sie wollen. Viele Bibliotheksfunktionen kehren zurück -1
auf Fehler.
Dies ist jedoch nicht immer möglich, insbesondere bei Funktionen, die normalerweise a zurückgeben Zeiger. Per Konvention kehren diese Funktionen zurück NULL
auf Fehler, Beispiele sind fopen()
und malloc()
.
Diese Rückgabecodes zeigen nur an, dass ein Fehler aufgetreten ist, nicht was der Fehler ist, normalerweise (bei Fehler) der globale errno
wird ebenfalls auf einen positiven Fehlercode gesetzt, der weitere Informationen liefert. Sehen Mann Fehlernr
Typischerweise gibt ein Linux-Programm bei Erfolg 0 oder bei Fehler ungleich Null zurück. Es gibt einige Ausnahmen (zum Beispiel grep, das Werte hat, um darzustellen, ob es eine Übereinstimmung gefunden hat). Der Grund dafür ist, dass die Bash-Eingabeaufforderung wahr als 0 und falsch als 1 definiert, was das Skripting vereinfacht:
somecmd && action "if succesful"
Aber das ist das Programm selbst. Für Code innerhalb eines Programms gibt es oft eine Mischung aus Konventionen. Eine übliche Methode ist die Rückgabe von 0 (oder positiv) bei Erfolg oder negativ bei Misserfolg. Der Grund dafür ist, dass alle Befehlssätze (die mir bekannt sind) eine Verzweigung-wenn-Null- oder Verzweigung-wenn-kleiner-als-Null-Anweisungen haben, was bedeutet, dass es nur eine Anweisung gibt, um den Vergleich durchzuführen (wie im Gegensatz zu einem Vergleich und dann einer Verzweigung, wenn der Vergleich übereinstimmt).
errno
ist eine globale Variable, die Sie mit der Fehlernummer setzen würden. Die Konvention ist festzulegen errno
und dann eine negative Zahl zurückgeben (normalerweise eine negative). Der negative Rückgabewert zeigt an errno
sollte überprüft werden. Wenn Sie Ihr Beispiel verwenden (und es in eine Funktion einfügen), könnte es so aussehen:
int allocate_buffer(char *buffer) {
buffer = malloc(1024);
if (buffer == NULL) {
errno = ENOMEM;
return -1;
}
return 0;
}
Der Aufrufer würde dann basierend auf dem Rückgabewert wissen, ob ein Fehler aufgetreten ist, und errno überprüfen, um zu sehen, was der Fehler war, und entscheiden, wie von dort aus weitergegangen werden soll.
5.1.2.2.3 Programmbeendigung
Wenn der Rückgabetyp der main-Funktion ein mit int kompatibler Typ ist, entspricht eine Rückkehr vom ersten Aufruf der main-Funktion dem Aufruf der Exit-Funktion mit dem von der main-Funktion zurückgegebenen Wert als 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 Hostumgebung zurückgegebene Beendigungsstatus unspezifiziert.
7.22.4.4 Die Ausgangsfunktion:
Schließlich wird die Steuerung an die Hostumgebung zurückgegeben. Wenn der Wert von status Null oder EXIT_SUCCESS ist, wird eine implementierungsdefinierte Form des Status erfolgreiche Beendigung zurückgegeben. Wenn der Wert von status EXIT_FAILURE ist, wird eine implementierungsdefinierte Form des Status fehlgeschlagene Beendigung zurückgegeben. Andernfalls ist der zurückgegebene Status implementierungsdefiniert.
Ich fand das selbsterklärend.
Du verwechselst Fehlercodes
errno
und Fehlercodes, von denen Sie zurückkehrenmain
. Das sind zwei verschiedene Dinge. Wenn Ihr Programm aus irgendeinem Grund fehlschlägt, kehren Sie zurückEXIT_FAILURE
ausmain
sonst zurückEXIT_SUCCESS
. Auch das kann interessant sein– Jabberwocky
13. November 2017 um 13:41 Uhr