So beenden Sie C ++ - Code

267

Ich möchte, dass mein C ++ - Code nicht mehr ausgeführt wird, wenn eine bestimmte Bedingung erfüllt ist, bin mir aber nicht sicher, wie ich das tun soll. Wenn also eine ifAussage wahr ist, beenden Sie den Code wie folgt:

if (x==1)
{
    kill code;
}
Der Nachtmensch
quelle
98
Verwenden Sie die richtige Logik. Bei main()Verwendung return, bei Funktionen wird ein korrekter Rückgabewert verwendet oder eine ordnungsgemäße Ausnahme ausgelöst. Nicht benutzen exit()!
Kay - SE ist böse
6
@JonathanLeffler: Wenn es mit NDEBUGdefined kompiliert wird , assertwird es wahrscheinlich zu einem No-Op. Sie sollten sich also nicht mehr darauf verlassen, als Fehler zu erkennen.
MvG
13
@jamesqf: a returnvon main()ist vollkommen logisch. Hiermit wird der vom Programm an das Betriebssystem gemeldete Exit-Code festgelegt, was in vielen Fällen hilfreich sein kann (wenn Ihr Programm beispielsweise als Teil eines größeren Prozesses verwendet werden kann).
AAT
11
Interessanterweise ist dieses Q ein Duplikat dieses vor 5 Jahren, dessen akzeptierte Antwort ganz anders ist: stackoverflow.com/questions/1116493/how-to-quit-ac-program Ich denke, die Community hat 5 Jahre gebraucht , um das blind zu lernen std :: exit aufrufen könnte schlecht sein?
Brandin
5
Fragen Warum wird die Verwendung exit()als schlecht angesehen? - SO 25141737 und Wie beende ich ein C ++ - Programm? - SO 1116493 sind jetzt als Duplikate dieses geschlossen. Die erste enthält einen Verweis auf "Nur-Crash-Software", der einen Blick wert sein könnte, wenn auch nur, um Sie zum Nachdenken über das Schreiben robuster Software anzuregen.
Jonathan Leffler

Antworten:

431

Es gibt verschiedene Möglichkeiten, aber zuerst müssen Sie verstehen, warum die Objektbereinigung wichtig ist, und daher ist der Grund std::exitunter C ++ - Programmierern marginalisiert.

RAII und Stack Unwinding

C ++ verwendet eine Redewendung namens RAII , was in einfachen Worten bedeutet, dass Objekte eine Initialisierung im Konstruktor und eine Bereinigung im Destruktor durchführen sollten. Zum Beispiel diestd::ofstream Klasse die Datei während des Konstruktors öffnen, dann führt der Benutzer Ausgabeoperationen für sie aus, und schließlich wird am Ende ihres Lebenszyklus, der normalerweise durch seinen Umfang bestimmt wird, der Destruktor aufgerufen, der die Datei im Wesentlichen schließt und leert Alle auf die Festplatte geschriebenen Inhalte.

Was passiert, wenn Sie nicht zum Destruktor gelangen, um die Datei zu leeren und zu schließen? Wer weiß! Möglicherweise werden jedoch nicht alle Daten in die Datei geschrieben.

Betrachten Sie zum Beispiel diesen Code

#include <fstream>
#include <exception>
#include <memory>

void inner_mad()
{
    throw std::exception();
}

void mad()
{
    auto ptr = std::make_unique<int>();
    inner_mad();
}

int main()
{
    std::ofstream os("file.txt");
    os << "Content!!!";

    int possibility = /* either 1, 2, 3 or 4 */;

    if(possibility == 1)
        return 0;
    else if(possibility == 2)
        throw std::exception();
    else if(possibility == 3)
        mad();
    else if(possibility == 4)
        exit(0);
}

Was bei jeder Möglichkeit passiert, ist:

  • Möglichkeit 1: Return verlässt im Wesentlichen den aktuellen Funktionsumfang, sodass es über das Ende des Lebenszyklus osinformiert ist, indem es seinen Destruktor aufruft und eine ordnungsgemäße Bereinigung durch Schließen und Leeren der Datei auf die Festplatte durchführt.
  • Möglichkeit 2: Durch das Auslösen einer Ausnahme wird auch der Lebenszyklus der Objekte im aktuellen Bereich berücksichtigt, wodurch eine ordnungsgemäße Bereinigung durchgeführt wird ...
  • Möglichkeit 3: Hier tritt das Abwickeln des Stapels in Aktion! Obwohl die Ausnahme ausgelöst wird inner_mad, durchläuft der Abwickler den Stapel von madund führt maineine ordnungsgemäße Bereinigung durch. Alle Objekte werden ordnungsgemäß zerstört, einschließlich ptrund os.
  • Möglichkeit 4: Nun, hier? exitist eine C-Funktion und weder bekannt noch kompatibel mit den C ++ - Redewendungen. Es werden keine Bereinigungen für Ihre Objekte durchgeführt, auch nicht osim selben Bereich. Ihre Datei wird also nicht richtig geschlossen und aus diesem Grund wird der Inhalt möglicherweise nie in sie geschrieben!
  • Andere Möglichkeiten: Es verlässt nur den Hauptbereich, indem es eine implizite Ausführung durchführt return 0und somit den gleichen Effekt wie Möglichkeit 1 hat, dh eine ordnungsgemäße Bereinigung.

Aber sei dir nicht so sicher, was ich dir gerade gesagt habe (hauptsächlich Möglichkeiten 2 und 3); Lesen Sie weiter und wir werden herausfinden, wie Sie eine ordnungsgemäße ausnahmebasierte Bereinigung durchführen.

Mögliche Möglichkeiten zum Beenden

Rückkehr von der Hauptstraße!

Sie sollten dies nach Möglichkeit tun. Ziehen Sie es immer vor, von Ihrem Programm zurückzukehren, indem Sie einen ordnungsgemäßen Exit-Status von main zurückgeben.

Der Aufrufer Ihres Programms und möglicherweise das Betriebssystem möchten möglicherweise wissen, ob das, was Ihr Programm tun sollte, erfolgreich ausgeführt wurde oder nicht. Aus dem gleichen Grund sollten Sie entweder Null zurückgeben oder EXIT_SUCCESSsignalisieren, dass das Programm erfolgreich beendet wurde, und EXIT_FAILUREum zu signalisieren, dass das Programm nicht erfolgreich beendet wurde , ist jede andere Form von Rückgabewert implementierungsdefiniert ( §18.5 / 8 ).

Sie befinden sich jedoch möglicherweise sehr tief im Aufrufstapel, und es kann schmerzhaft sein, alles zurückzugeben ...

[Nicht] eine Ausnahme auslösen

Durch das Auslösen einer Ausnahme wird eine ordnungsgemäße Objektbereinigung mithilfe des Abwickelns des Stapels durchgeführt, indem der Destruktor jedes Objekts in einem früheren Bereich aufgerufen wird.

Aber hier ist der Haken ! Es ist implementierungsdefiniert, ob das Abwickeln des Stapels durchgeführt wird, wenn eine ausgelöste Ausnahme nicht behandelt wird (durch die catch (...) -Klausel) oder selbst wenn Sie eine noexceptFunktion in der Mitte des Aufrufstapels haben. Dies ist in §15.5.1 [außer.terminate] angegeben :

  1. In einigen Situationen muss die Ausnahmebehandlung für weniger subtile Fehlerbehandlungstechniken abgebrochen werden. [Hinweis: Diese Situationen sind:

    [...]

    - wenn der Ausnahmebehandlungsmechanismus keinen Handler für eine ausgelöste Ausnahme finden kann (15.3) oder wenn die Suche nach einem Handler (15.3) auf den äußersten Block einer Funktion mit einer noexceptSpezifikation stößt, die die Ausnahme nicht zulässt (15.4), oder [...]

    [...]

  2. In solchen Fällen heißt std :: terminate () (18.8.3). In der Situation, in der kein passender Handler gefunden wird, wird implementierungsdefiniert, ob der Stapel abgewickelt wird, bevor std :: terminate () [...] aufgerufen wird.

Also müssen wir es fangen!

Wirf eine Ausnahme und fange sie an der Hauptleitung!

Da nicht erfasste Ausnahmen möglicherweise kein Abwickeln des Stapels durchführen (und folglich keine ordnungsgemäße Bereinigung durchführen) , sollten wir die Ausnahme in main abfangen und dann einen Exit-Status zurückgeben ( EXIT_SUCCESSoderEXIT_FAILURE ) zurückgeben.

Ein möglicherweise gutes Setup wäre also:

int main()
{
    /* ... */
    try
    {
        // Insert code that will return by throwing a exception.
    }
    catch(const std::exception&)  // Consider using a custom exception type for intentional
    {                             // throws. A good idea might be a `return_exception`.
        return EXIT_FAILURE;
    }
    /* ... */
}

[Nicht] std :: exit

Dies führt keine Abwicklung des Stapels durch, und kein lebendes Objekt auf dem Stapel ruft seinen jeweiligen Destruktor auf, um eine Bereinigung durchzuführen.

Dies wird in §3.6.1 / 4 [basic.start.init] durchgesetzt :

Das Beenden des Programms ohne Verlassen des aktuellen Blocks (z. B. durch Aufrufen der Funktion std :: exit (int) (18.5)) zerstört keine Objekte mit automatischer Speicherdauer (12.4) . Wenn std :: exit aufgerufen wird, um ein Programm während der Zerstörung eines Objekts mit statischer oder Thread-Speicherdauer zu beenden, hat das Programm ein undefiniertes Verhalten.

Denken Sie jetzt darüber nach, warum sollten Sie so etwas tun? Wie viele Gegenstände haben Sie schmerzhaft beschädigt?

Andere [als schlechte] Alternativen

Es gibt andere Möglichkeiten, ein Programm zu beenden (außer Abstürzen) , aber sie werden nicht empfohlen. Nur zur Verdeutlichung werden sie hier vorgestellt. Beachten Sie, wie normale Programmbeendigung nicht mittleres Stack Abwickeln , sondern eine Ordnung Zustand für das Betriebssystem.

  • std::_Exit verursacht eine normale Programmbeendigung, und das war's.
  • std::quick_exitbewirkt eine normale Programmbeendigung und ruft std::at_quick_exitHandler auf, es wird keine weitere Bereinigung durchgeführt.
  • std::exitverursacht eine normale Programmbeendigung und ruft dann std::atexitHandler auf. Andere Arten von Bereinigungen werden durchgeführt, z. B. das Aufrufen von Destruktoren für statische Objekte.
  • std::abortverursacht eine abnormale Programmbeendigung, es wird keine Bereinigung durchgeführt. Dies sollte aufgerufen werden, wenn das Programm auf eine wirklich, wirklich unerwartete Weise beendet wurde. Es wird nichts anderes tun, als dem Betriebssystem die abnormale Beendigung zu signalisieren. Einige Systeme führen in diesem Fall einen Core-Dump durch.
  • std::terminateruft das auf, std::terminate_handlerwas std::abortstandardmäßig aufruft .
Denilson Amorim
quelle
25
Dies ist sehr informativ: Insbesondere habe ich nie bemerkt, dass das Auslösen einer Ausnahme, die nirgendwo behandelt wird (zum Beispiel: Einige newWürfe std::bad_allocund Ihr Programm haben vergessen, diese Ausnahme irgendwo abzufangen), den Stapel vor dem Beenden nicht ordnungsgemäß abwickelt. Dies scheint dumm zu mir: Es wäre leicht gewesen , um im wesentlichen den Anruf wickelt mainin einem trivialen try{- }catch(...){}Block, der das Abwickeln Stapel gewährleisten würde , ist in solchen Fällen richtig gemacht, ohne Kosten ( und damit meine ich: Programme nicht dies mit zahlt nicht Elfmeter). Gibt es einen bestimmten Grund, warum dies nicht getan wird?
Marc van Leeuwen
12
@MarcvanLeeuwen Ein möglicher Grund ist das Debuggen: Sie möchten in den Debugger einbrechen, sobald eine nicht behandelte Ausnahme ausgelöst wird. Wenn Sie den Stapel abwickeln und eine Bereinigung durchführen, wird der Kontext gelöscht, der den Absturz verursacht hat, den Sie debuggen möchten. Wenn kein Debugger vorhanden ist, ist es möglicherweise besser, den Core zu sichern, damit eine postmortale Analyse durchgeführt werden kann.
Hugh Allen
11
Manchmal ist mein Browser fehlerhaft (ich beschuldige Flash) und verbraucht mehrere Gigabyte RAM, und mein Betriebssystem speichert Seiten auf der Festplatte, wodurch alles langsam wird. Wenn ich den Browser schließe, wird der Stapel ordnungsgemäß abgewickelt, was bedeutet, dass all diese Gigabyte RAM von der Festplatte gelesen und in den Speicher kopiert werden, um freigegeben zu werden. Dies dauert ungefähr eine Minute. Ich wünschte, sie hätten std::abortstattdessen verwendet, damit das Betriebssystem alle Speicher, Sockets und Dateideskriptoren freigeben kann, ohne sie für eine Minute auszutauschen.
nwp
2
@nwp, ich verstehe das Gefühl. Aber sofortiges Töten kann Dateien beschädigen, meine neuesten Tabs nicht speichern usw. :)
Paul Draper
2
@PaulDraper Ich würde es sicherlich nicht für erträglich halten, wenn ein Browser die vor einem Stromausfall geöffneten Registerkarten nicht wiederherstellen könnte. Wenn ich gerade einen Tab geöffnet hätte und noch keine Zeit gehabt hätte, ihn zu speichern, wäre er natürlich verloren. Aber abgesehen davon gibt es keine Entschuldigung dafür, es zu verlieren.
Kasperd
61

Wie Martin York erwähnte, führt der Ausgang keine notwendige Bereinigung durch, wie dies bei der Rückgabe der Fall ist.

Es ist immer besser, die Rückgabe anstelle des Ausgangs zu verwenden. Wenn Sie sich nicht in main befinden, wo immer Sie das Programm beenden möchten, kehren Sie zuerst zu main zurück.

Betrachten Sie das folgende Beispiel. Mit dem folgenden Programm wird eine Datei mit dem genannten Inhalt erstellt. Wenn die Rückgabe jedoch kommentiert und nicht kommentiert ist (0), versichert Ihnen der Compiler nicht, dass die Datei den erforderlichen Text enthält.

int main()
{
    ofstream os("out.txt");
    os << "Hello, Can you see me!\n";
    return(0);
    //exit(0);
}

Nicht nur das, mehrere Exit-Punkte in einem Programm erschweren das Debuggen. Verwenden Sie exit nur, wenn dies gerechtfertigt werden kann.

Narendra N.
quelle
2
Was empfehlen Sie, um dieses Verhalten in einem etwas größeren Programm zu erreichen? Wie kehren Sie immer sauber zu main zurück, wenn irgendwo tiefer im Code eine Fehlerbedingung ausgelöst wird, die das Programm beenden sollte?
Janusz
5
@Janusz, In diesem Fall können Sie Ausnahmen verwenden / auslösen, wenn Sie keinen vordefinierten Wert zurückgeben, dh einen Rückgabewert von der Funktion haben, z. B. 0 zurückgeben, wenn erfolgreich, 1 im Fehlerfall, aber die Ausführung fortsetzen , -1 im Fehlerfall & Programm beenden. Basierend auf dem Rückgabewert der Funktion, wenn dies ein Fehler ist, kehren Sie einfach vom Hauptwert zurück, nachdem Sie weitere Bereinigungsaktivitäten ausgeführt haben. Verwenden Sie exit mit Bedacht, ich möchte es nicht vermeiden.
Narendra N
1
@NarendraN, "notwendige Bereinigung" ist vage - das Betriebssystem sorgt dafür (Windows / Linux), dass Speicher- und Dateihandles ordnungsgemäß freigegeben werden. Bezüglich der "fehlenden" Dateiausgabe: Wenn Sie darauf bestehen, dass dies ein echtes Problem sein könnte, lesen Sie stackoverflow.com/questions/14105650/how-does-stdflush-work. Wenn Sie eine Fehlerbedingung haben , zeigt Ihnen die ordnungsgemäße Protokollierung, dass Ihr Programm hat einen undefinierten Status erreicht und Sie können einen Haltepunkt direkt vor Ihrem Protokollierungspunkt festlegen. Wie erschwert das das Debuggen?
Markus
2
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
return (EXIT_SUCCESS);stattdessen für modernes C ++ return(0)
Jonas Stein
39

Rufen Sie die std::exitFunktion auf.   

Otávio Décio
quelle
2
Welche Objektzerstörer werden aufgerufen, wenn Sie diese Funktion aufrufen?
Rob Kennedy
37
exit () kehrt nicht zurück. Es kann also kein Abwickeln des Stapels stattfinden. Nicht einmal globale Objekte werden nicht zerstört. Die mit atexit () registrierten Funktionen werden jedoch aufgerufen.
Martin York
16
Bitte rufen Sie nicht an, exit()wenn Ihr Bibliothekscode in meinem Host-Prozess ausgeführt wird - letzterer wird mitten im Nirgendwo beendet.
Scharfzahn
5
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
23

Die Leute sagen "Call Exit (Rückkehrcode)", aber das ist eine schlechte Form. In kleinen Programmen ist es in Ordnung, aber es gibt eine Reihe von Problemen damit:

  1. Sie werden am Ende mehrere Austrittspunkte aus dem Programm haben
  2. Dadurch wird der Code komplizierter (wie bei der Verwendung von goto).
  3. Es kann keinen zur Laufzeit zugewiesenen Speicher freigeben

Wirklich, das einzige Mal, wenn Sie das Problem beenden sollten, ist mit dieser Zeile in main.cpp:

return 0;

Wenn Sie exit () verwenden, um Fehler zu behandeln, sollten Sie sich mit Ausnahmen (und Verschachtelungsausnahmen) als einer viel eleganteren und sichereren Methode vertraut machen.

jkeys
quelle
9
In einer Umgebung mit mehreren Threads wird eine in einem anderen Thread ausgelöste Ausnahme nicht über main () behandelt. Vor Ablauf des untergeordneten Threads ist eine manuelle Kommunikation zwischen verschiedenen Threads erforderlich.
Steve Gilham
3
1. und 2. sind Sache des Programmierers. Bei ordnungsgemäßer Protokollierung ist dies kein Problem, da die Exeuktion für immer stoppt. Was 3 betrifft: Das ist einfach falsch, das Betriebssystem gibt den Speicher frei - möglicherweise ohne eingebettete Geräte / Echtzeit, aber wenn Sie das tun, kennen Sie sich wahrscheinlich aus.
Markus
1
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
1
Wenn jedoch ein Fehler aufgetreten ist, sollten Sie 0 nicht zurückgeben. Sie sollten 1 zurückgeben (oder möglicherweise einen anderen Wert, aber 1 ist immer eine sichere Wahl).
Kef Schecter
14

return 0;Setzen Sie das, wo immer Sie wollen, int main()und das Programm wird sofort geschlossen.

Evan Carslake
quelle
the-nightman, @ evan-carslake und alle anderen, ich möchte auch hinzufügen, dass diese SO- Frage Nr. 36707 eine Diskussion darüber enthält, ob eine return-Anweisung nur irgendwo in einer Routine auftreten sollte. Dies ist eine Lösung; Abhängig von der spezifischen Situation würde ich jedoch nicht sagen, dass dies die beste Lösung ist.
localhost
1
OP sagte nichts darüber, daher denke ich, dass es ziemlich voreilig ist anzunehmen, dass der Code innerhalb der Funktion sein sollte main.
Marc van Leeuwen
@localhost Eine return-Anweisung ist in jeder Situation und unter allen Bedingungen völlig optional. Ist int main()jedoch anders. Das Programm int main()beginnt und endet. Es gibt keinen anderen Weg, dies zu tun. Das Programm wird ausgeführt, bis Sie true oder false zurückgeben. Fast die ganze Zeit geben Sie 1 oder true zurück, um anzuzeigen, dass das Programm korrekt geschlossen wurde (z. B. false, wenn Sie keinen Speicher freigeben konnten oder aus welchem ​​Grund auch immer). Es ist immer eine schlechte Idee, das Programm selbst ausführen zu lassen. Beispiel:int main() { int x = 2; int foo = x*5; std::cout << "blah"; }
Evan Carslake
@EvanCarslake Verstanden, wenn Sie einen Kommentar bemerkt haben, den ich an anderer Stelle für diese Frage gepostet habe, bin ich mit diesem Thema vertraut int main. Es ist jedoch nicht immer eine gute Idee, mehrere return-Anweisungen in einer Hauptroutine zu haben. Eine mögliche Einschränkung besteht darin, die Lesbarkeit des Codes zu verbessern. Verwenden Sie jedoch so etwas wie ein boolesches Flag, das den Status ändert, um zu verhindern, dass bestimmte Codeabschnitte des Codes in diesem Anwendungsstatus ausgeführt werden. Persönlich finde ich, dass eine gemeinsame return-Anweisung die meisten Anwendungen besser lesbar macht. Zuletzt Fragen zur Speicherbereinigung und zum ordnungsgemäßen Schließen von E / A-Objekten vor dem Beenden.
localhost
2
@EvanCarslake Sie nicht zurück truevon maineiner korrekten Beendigung anzuzeigen. Sie müssen Null oder EXIT_SUCCESS(oder, wenn Sie möchten, falsedie implizit in Null konvertiert werden) zurückgeben, um eine normale Beendigung anzuzeigen. Um einen Fehler anzuzeigen, können Sie zurückkehren EXIT_FAILURE. Jede andere Codebedeutung ist implementierungsdefiniert (auf POSIX-Systemen würde dies den tatsächlichen Fehlercode bedeuten).
Ruslan
11

Das Programm wird beendet, wenn der Ausführungsablauf das Ende der Hauptfunktion erreicht.

Um es vorher zu beenden, können Sie die Funktion exit (int status) verwenden, wobei status ein Wert ist, der an den Start des Programms zurückgegeben wird. 0 zeigt normalerweise einen fehlerfreien Zustand an

Chrisbunney
quelle
2
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
11

Geben Sie entweder einen Wert von Ihrem zurück mainoder verwenden Sie die exitFunktion. Beide nehmen eine int. Es spielt keine Rolle, welchen Wert Sie zurückgeben, es sei denn, Sie haben einen externen Prozess, der nach dem Rückgabewert sucht.

Goz
quelle
3
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
11

Wenn Sie irgendwo tief im Code einen Fehler haben, lösen Sie entweder eine Ausnahme aus oder legen Sie den Fehlercode fest. Es ist immer besser, eine Ausnahme auszulösen, als Fehlercodes festzulegen.

Jagannath
quelle
2
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
9

Im Allgemeinen würden Sie die exit()Methode mit einem geeigneten Exit-Status verwenden .

Null würde einen erfolgreichen Lauf bedeuten. Ein Status ungleich Null zeigt an, dass ein Problem aufgetreten ist. Dieser Exit-Code wird von übergeordneten Prozessen (z. B. Shell-Skripten) verwendet, um festzustellen, ob ein Prozess erfolgreich ausgeführt wurde.

Brian Agnew
quelle
1
Die Verwendung von exit kann bedeuten, dass Sie ein Designproblem haben. Wenn ein Programm korrekt funktioniert, sollte es nur bei main beendet werden return 0;. Ich gehe davon aus, dass exit()es assert(false);so ist und daher nur in der Entwicklung verwendet werden sollte, um Probleme frühzeitig zu erkennen.
CoffeDeveloper
2
Beachten Sie, dass diese Antwort aus der Frage zum Beenden eines C ++ - Programms zusammengeführt wurde. - SO 1116493 . Diese Antwort wurde ungefähr 6 Jahre vor dieser Frage geschrieben.
Jonathan Leffler
7

Über den Aufruf von exit (error_code) hinaus, der atexit-Handler, aber keine RAII-Destruktoren usw. aufruft, verwende ich immer mehr Ausnahmen.

Mein Hauptprogramm sieht immer mehr so ​​aus

int main(int argc, char** argv) 
{
    try {
        exit( secondary_main(argc, argv );
    }
    catch(...) {
        // optionally, print something like "unexpected or unknown exception caught by main"
        exit(1);
    }
}

Dabei wird sekundäres_Main dort abgelegt, wo das gesamte ursprünglich platzierte Material abgelegt wird - dh das ursprüngliche Haupt wird in sekundäres_Main umbenannt und das obige Stub-Haupt wird hinzugefügt. Dies ist nur eine Kleinigkeit, damit nicht zu viel Code zwischen dem Fach und dem Hauptfang vorhanden ist.

Wenn Sie möchten, fangen Sie andere Ausnahmetypen ab.
Ich mag es, String-Fehlertypen wie std :: string oder char * abzufangen und diese im catch-Handler in main zu drucken.

Mit solchen Ausnahmen können zumindest RAII-Destruktoren aufgerufen werden, damit sie bereinigen können. Welches kann angenehm und nützlich sein.

Insgesamt spielen C-Fehlerbehandlung - Exit und Signale - und C ++ - Fehlerbehandlung - Try / Catch / Throw-Ausnahmen - bestenfalls inkonsistent zusammen.

Dann, wo Sie einen Fehler erkennen

throw "error message"

oder ein spezifischerer Ausnahmetyp.

Krazy Glew
quelle
Übrigens: Mir ist klar, dass die Verwendung eines Datentyps wie einer Zeichenfolge, die eine dynamische Speicherzuweisung beinhalten kann, in oder um einen Ausnahmebehandler für Ausnahmen, die möglicherweise mit einem Speichermangel zusammenhängen, keine gute Idee ist. String-Konstanten im C-Stil sind kein Problem.
Krazy Glew
1
Es macht keinen Sinn, exitIhr Programm aufzurufen . Da du drin bist main, kannst du einfach return exitCode;.
Ruslan
-1

Wenn sich Ihre if-Anweisung in Loop befindet, können Sie verwenden

 break; 

Wenn Sie einem Code entkommen und die Schleife fortsetzen möchten, verwenden Sie:

fortsetzen;

Wenn Ihre if-Anweisung nicht in Loop ist, können Sie Folgendes verwenden:

 return 0;

Or 




  exit();
Akshay
quelle
-2

Dude ... exit()Funktion ist unter stdlib.h definiert

Sie müssen also einen Präprozessor hinzufügen.

Fügen Sie include stdlib.hden Header-Bereich ein

Verwenden exit();Sie dann, wo immer Sie möchten, aber denken Sie daran, eine Interger-Nummer in die Klammer von exit zu setzen.

beispielsweise:

exit(0);
rdxxdroid
quelle
-2

Wenn der Zustand, auf den ich teste, wirklich schlechte Nachrichten sind, mache ich Folgendes:

*(int*) NULL= 0;

Dies gibt mir einen schönen Kern, von dem aus ich die Situation untersuchen kann.

Dodo
quelle
4
Dies kann durchaus optimiert werden, da es zu undefiniertem Verhalten führt. Tatsächlich kann der gesamte Ausführungszweig mit einer solchen Anweisung vom Compiler gelöscht werden.
Ruslan
-2

Um eine Bedingung zu brechen, verwenden Sie die Rückgabe (0).

In Ihrem Fall wäre es also:

    if(x==1)
    {
        return 0;
    }
Lavendel
quelle