Gibt es einen Unterschied zwischen return n
(in der main
Funktion) und exit(n)
in C? Ist es durch C- oder POSIX-Standards definiert oder hängt es vom Betriebssystem oder Compiler ab?
In den meisten Fällen gibt es keinen Unterschied, aber hier ist ein C-Programm, das sich wahrscheinlich unterschiedlich verhält, je nachdem, ob es verwendet wird return 0;
oder exit(0);
:
#include <stdio.h>
#include <stdlib.h>
static char *message;
void cleanup(void) {
printf("message = \"%s\"\n", message);
}
int main(void) {
char local_message[] = "hello, world";
message = local_message;
atexit(cleanup);
#ifdef USE_EXIT
puts("exit(0);");
exit(0);
#else
puts("return 0;");
return 0;
#endif
}
Aufgrund des atexit()
Aufrufs wird die Funktion entweder exit(0);
oder aufgerufen. Der Unterschied besteht darin, dass beim Aufrufen des Programms die Bereinigung erfolgt, während der "Aufruf" von noch aktiv ist, sodass das Objekt weiterhin vorhanden ist. Das Ausführen beendet jedoch sofort den Aufruf von und ruft dann die Funktion auf. Da (über den globalen Zeiger) auf ein Objekt verwiesen wird, das lokal zugeordnet ist und dieses Objekt nicht mehr vorhanden ist, ist das Verhalten undefiniert.return 0;
cleanup
exit(0);
main()
local_message
return 0;
main()
cleanup()
cleanup()
message
main
Hier ist das Verhalten, das ich auf meinem System sehe:
$ gcc -DUSE_EXIT c.c -o c && ./c
exit(0);
message = "hello, world"
$ gcc c.c -o c && ./c
return 0;
message = ""
$
Das Ausführen des Programms ohne -DUSE_EXIT
kann alles tun, einschließlich Absturz oder Drucken "hello, world"
(wenn der von verwendete Speicher local_message
nicht überlastet ist).
In der Praxis zeigt sich dieser Unterschied jedoch nur, wenn lokal definierte Objekte main()
außerhalb sichtbar gemacht werden, main()
indem Zeiger darauf gespeichert werden. Dies könnte plausibel passieren für argv
. (Experimente auf meinem System zeigen, dass die Objekte, auf die nach argv
und nach verwiesen wird, *argv
nach der Rückkehr weiterhin vorhanden sind main()
, aber darauf sollten Sie sich nicht verlassen.)
Für C
Der Standard besagt, dass eine Rückkehr vom ersten Aufruf zu main dem Aufruf von exit entspricht. Es ist jedoch nicht zu erwarten, dass eine Rückgabe von main funktioniert, wenn während der Bereinigung möglicherweise lokale Daten zu main benötigt werden.
Für C ++
Wenn exit (0) zum Beenden des Programms verwendet wird, werden Destruktoren für nicht statische Objekte mit lokalem Gültigkeitsbereich nicht aufgerufen. Destruktoren werden jedoch aufgerufen, wenn return 0 verwendet wird.
Programm 1 - - verwendet exit (0) zum Beenden
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
Test t1;
// using exit(0) to exit from main
exit(0);
}
Ausgabe: Im Konstruktor des Tests
Programm 2 - verwendet return 0 zum Beenden
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
}
};
int main() {
Test t1;
// using return 0 to exit from main
return 0;
}
Ausgabe: Innerhalb des Testkonstruktors
Innerhalb des Testdestruktors
Das Aufrufen von Destruktoren ist manchmal wichtig, beispielsweise wenn der Destruktor über Code verfügt, um Ressourcen wie das Schließen von Dateien freizugeben.
Beachten Sie, dass statische Objekte auch dann bereinigt werden, wenn wir exit () aufrufen. Siehe zum Beispiel folgendes Programm.
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
class Test {
public:
Test() {
printf("Inside Test's Constructor\n");
}
~Test(){
printf("Inside Test's Destructor");
getchar();
}
};
int main() {
static Test t1; // Note that t1 is static
exit(0);
}
Ausgabe: Innerhalb des Testkonstruktors
Innerhalb des Testdestruktors
finally
Es ist erwähnenswert, dass der C-Standard (C99) zwei Arten von Ausführungsumgebungen definiert: Freistehende Umgebung und Gehostete Umgebung . Die freistehende Umgebung ist eine C-Umgebung, die die C-Bibliotheken nicht unterstützt und für eingebettete Anwendungen und dergleichen vorgesehen ist. Eine AC-Umgebung, die die C-Bibliotheken unterstützt, wird als gehostete Umgebung bezeichnet.
Laut C99 ist in einer freistehenden Umgebung die Beendigung eines Programms definiert. Wenn also die Implementierung definiert
main
,return n
undexit
, ist ihr Verhalten so, wie es in dieser Implementierung definiert ist.C99 definiert das Verhalten der gehosteten Umgebung als:
quelle
Aus der Sicht des C-Standards nicht wirklich, außer
return
eine Aussage undexit()
eine Funktion zu sein. In beiden Fällen werden alle mit registrierten Funktionenatexit()
aufgerufen und das Programm beendet.Es gibt einige Situationen, auf die Sie achten sollten:
main()
. Während es in der Praxis selten zu sehen ist, ist es in C legal (C ++ verbietet es ausdrücklich.)main()
. Manchmal wird ein vorhandenesmain()
in etwas anderes umbenannt und von einem neuen aufgerufenmain()
.Die Verwendung von
exit()
führt zu einem Fehler, wenn einer dieser Fehler auftritt, nachdem Sie den Code geschrieben haben, insbesondere wenn er nicht abnormal beendet wird. Um dies zu vermeiden, ist es eine gute Idee, die Gewohnheit zu haben, siemain()
als die Funktion zu behandeln , die sie ist, und sie zu verwenden,return
wenn Sie möchten, dass sie endet.quelle