HOWTO · C++

exit(1) in C++

Dieser Artikel zeigt, wie Sie die Exit-Funktion in C++ verwenden

Auf dieser Seite

exit(1) beendet ein C++-Programm üblicherweise mit einem Status ungleich null und signalisiert der aufrufenden Umgebung damit einen Fehler. Ein Status von null steht üblicherweise für Erfolg. In C++ heißt die Funktion std::exit und ist in <cstdlib> deklariert; für die standardisierten Statuswerte verwenden Sie EXIT_SUCCESS und EXIT_FAILURE. Eine Rückkehr aus main ist meist vorzuziehen, weil lokale Objekte dabei regulär aufgeräumt werden.

Was std::exit in C++ bewirkt

Die Funktion std::exit übernimmt einen ganzzahligen Statuswert und beendet das Programm, ohne zu ihrem Aufrufer zurückzukehren. Die geläufige Schreibweise exit(1) bezeichnet die C-Bibliotheksfunktion; verwenden Sie in C++ den qualifizierten Namen std::exit, um den Namensraum ausdrücklich anzugeben. Mit den Konstanten EXIT_SUCCESS und EXIT_FAILURE lassen sich standardisierte Erfolgs- und Fehlerstatuswerte ausdrücken, ohne für Fehler einen bestimmten Zahlenwert vorauszusetzen.

Bei einer normalen Beendigung über std::exit werden die mit std::atexit registrierten Funktionen aufgerufen, Objekte mit statischer Speicherdauer zerstört sowie C-Streams geleert und geschlossen. Der aktuelle Aufrufstapel wird dabei nicht abgewickelt: Automatische Objekte in der Funktion, die std::exit aufruft, werden nicht zerstört. Das ist relevant, wenn diese Objekte Ressourcen besitzen, die durch Destruktoren freigegeben werden müssen.

std::exit mit einem Statuscode verwenden

Verwenden Sie std::exit(EXIT_SUCCESS), wenn eine Funktion außerhalb von main das gesamte Programm erfolgreich beenden muss. Eine Rückgabe eines Statuswerts aus main ist jedoch meist leichter nachzuvollziehen. Das folgende Beispiel gibt die englische Meldung „Operation completed“ aus:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <cstdlib>
#include <iostream>

int main() {
    std::cout << "Operation completed" << '\n';
    std::exit(EXIT_SUCCESS);
}
Operation completed

Bei einem schwerwiegenden Fehler, für den es keine sinnvolle Wiederherstellung gibt, geben Sie das Problem aus und beenden Sie das Programm mit std::exit(EXIT_FAILURE). In diesem eigenständigen Programm wählt --fail diesen Pfad aus; ohne das Argument wird es normal beendet. Die Fehlermeldung wird auf Englisch ausgegeben („Unable to continue“); bei normalem Abschluss lautet die englische Meldung „Operation completed“. Die Diagnose geht an die Standardfehlerausgabe. Der gewählte Status teilt der aufrufenden Umgebung mit, ob der Vorgang erfolgreich war:

#include <cstdlib>
#include <iostream>
#include <string_view>

int main(int argc, char* argv[]) {
    if (argc > 1 && std::string_view(argv[1]) == "--fail") {
        std::cerr << "Unable to continue" << '\n';
        std::exit(EXIT_FAILURE);
    }

    std::cout << "Operation completed" << '\n';
    return EXIT_SUCCESS;
}

Was bei einer normalen Beendigung ausgeführt wird

Das Aufräumverhalten ist selektiv. Registrierte std::atexit-Funktionen werden ausgeführt, Objekte mit statischer Speicherdauer werden zerstört und C-Streams werden geleert und geschlossen. Automatische Objekte in der Funktion, die std::exit aufruft, bleiben unberührt, weil der Aufruf nicht regulär durch ihre Gültigkeitsbereiche zurückkehrt. Verlassen Sie sich deshalb bei der Verwendung von std::exit nicht darauf, dass lokale Destruktoren eine Datei, eine Sperre oder eine andere Ressource freigeben. Erledigen Sie die Bereinigung vorher oder kehren Sie regulär über den Gültigkeitsbereich zurück, dem die Ressource gehört.

Ein Status übermittelt das Ergebnis des Programms, beschreibt den Fehler aber nicht von selbst. Geben Sie vor dem Beenden eine hilfreiche Diagnose aus oder schreiben Sie sie in ein Protokoll, und dokumentieren Sie anwendungsspezifische Statuswerte für die Aufrufer. Für portable Konventionen für Erfolg und Fehler verwenden Sie EXIT_SUCCESS und EXIT_FAILURE aus <cstdlib>.

Bereinigungsfunktionen mit std::atexit registrieren

Registrieren Sie eine Funktion mit std::atexit, wenn sie bei einer normalen Beendigung über std::exit oder bei einer Rückkehr aus main ausgeführt werden soll. Die Funktionen laufen in umgekehrter Registrierungsreihenfolge. Sie sollten begrenzte Aufräumarbeiten erledigen und nicht von automatischen Objekten in der Funktion abhängen, die die Beendigung ausgelöst hat.

Das eigenständige Beispiel registriert zwei Rückruffunktionen mit unterschiedlichen englischen Ausgabelabels. Diese bleiben im unveränderten Beispiel englisch: Zuerst wird „main work“ ausgegeben; da die Rückruffunktionen in umgekehrter Registrierungsreihenfolge laufen, folgt „release cache“ vor „close log“:

Der Code und die angezeigten Bezeichnungen oder Ausgaben in diesem Abschnitt bleiben auf Englisch.

#include <cstdlib>
#include <iostream>

void close_log() {
    std::cout << "close log" << '\n';
}

void release_cache() {
    std::cout << "release cache" << '\n';
}

int main() {
    std::atexit(close_log);
    std::atexit(release_cache);
    std::cout << "main work" << '\n';
    return EXIT_SUCCESS;
}
main work
release cache
close log

Wann Sie stattdessen aus main zurückkehren sollten

Eine Rückkehr aus main ist üblich, wenn die normale Arbeit abgeschlossen ist oder ein Ergebnis über die Aufrufkette zurückgegeben werden kann. Die zurückgegebene Ganzzahl wird zum Programmstatus, und lokale automatische Objekte in main werden beim Verlassen der Funktion zerstört. So können auch umschließende Funktionen und Destruktoren ihre reguläre Bereinigung abschließen.

Verwenden Sie std::exit, wenn das Programm aus einer tiefer verschachtelten Funktion heraus beendet werden muss und sich die Entscheidung nicht bequem durch normale Rückgaben weitergeben lässt. Berücksichtigen Sie vorher, welche automatischen Objekte dabei nicht zerstört werden. Bei behandelbaren Fehlern geben Sie einen Fehlerwert zurück oder leiten Sie eine Ausnahme an eine geeignete Stelle weiter. Beenden Sie den gesamten Prozess nur dann, wenn eine Fortsetzung nicht sinnvoll ist.