Richtig beenden das Programm. Mit Ausnahmen
Frage: Ist mit Ausnahmen der richtige Weg, um zu beenden mein Programm, wenn ich will eine Fehlermeldung angezeigt, und in der Nähe (Buchhaltung, die ich kann tief in das Programm)? Kann ich nur ausdrücklich nennen so etwas wie exit() statt?
, Was ich bin Derzeit Dabei:
Arbeite ich an einem Spiel-Projekt, und ich versuche, herauszufinden, der beste Weg, um das Programm zu beenden im Falle eines Fehlers, die Anrufe für eine solche Aktion. Zum Beispiel, in dem Fall die Texturen können nicht geladen werden ich eine Fehlermeldung angezeigt, und beenden Sie das Programm.
Ich bin derzeit dabei, dies mit Ausnahmen, etwa so:
int main()
{
Game game;
try
{
game.run();
}
catch (BadResolutionException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Resolution");
return 1;
}
catch (BadAssetException & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Assets");
return 1;
}
catch (std::bad_alloc & e)
{
Notification::showErrorMessage(e.what(), "ERROR: Memory");
return 1;
}
return 0;
}
Alle, aber bad_alloc sind meine selbst definierte exceptions abgeleitet von runtime_error.
Ich brauche keine manuelle ressourcenfreigabe und ich bin mit std::unique_ptr für alle dynamischen Zuweisung. Ich brauche nur um die Anzeige der Fehlermeldung und schließen Sie das Programm.
Forschung/Alternativen zu den Ausnahmen:
Ich habe mir eine Menge Beiträge zu SO und anderen stellen gesehen haben, die anderen sagen nichts von nicht, Ausnahmen, Ausnahmen aber Ihre mithilfe Sie falsch. Ich habe auch nachgeschaut ausdrücklich etwas rufen wie exit().
Mit exit() klingt nett, aber ich lese es nicht, gehe zurück durch den call-stack bis zur Hauptreinigung alles (wenn ich finden kann, diese wieder poste ich den link). Zusätzlich, nach http://www.cplusplus.com/reference/cstdlib/exit/ dies sollte nicht verwendet werden, wenn mehrere threads aktiv sind. Ich erwarte zu erstellen, einen zweiten thread für eine kurze Zeit zumindest einmal, und ein Fehler konnte auftreten in diesem thread.
Nicht mit Ausnahmen erwähnt wurde in einigen Antworten hier in Bezug auf Spiele https://gamedev.stackexchange.com/questions/103285/how-industy-games-handle-their-code-errors-and-exceptions
Ausnahmen wurde hier diskutiert: http://www.quora.com/Why-do-some-people-recommend-not-using-exception-handling-in-C++
Gibt es eine Reihe von anderen Quellen, die ich gelesen habe aber das waren die letzten, die ich sah.
Persönliches Fazit:
Aufgrund meiner begrenzten Erfahrung in der Arbeit mit Fehlerbehandlung und-mit Ausnahmen, ich bin mir nicht sicher, ob ich auf dem richtigen Weg. Ich habe mich entschlossen die Strecke mit Ausnahmen basierend auf dem code, den ich oben gepostet. Wenn Sie einverstanden sind, dass ich angehen sollte jenen Fällen, mit Ausnahmen, verwende ich es richtig?
- Look at std::exit, bevor Sie viel Zeit verbringen Sie auf beenden. Es macht einen besseren job, von sauber bis in eine RAII Welt.
- Inwiefern macht es einen besseren job? Es schadet auch nicht, entspannen Sie den Stapel...
- Gut, auch wenn Sie nicht es zu erwähnen, sollten Sie nicht rufen Sie
exit()
in der Mitte der Klasse oder die Bibliothek-code. stackoverflow.com/questions/22843189/... Also, wenn Sie denken, etwas wie das, nicht. - Nachdem Sie eine Bibliothek an: Niemals etwas beenden des Programms, es sei denn, es ist schwerer. Ähnliches gilt für eine eigenständige ausführbare Datei.
- Jeder Zeit gibt es eine Frage, Wann Ausnahmen es zwangsläufig geschlossen ist. Es ist eine legitime Frage. Aufhören zu versuchen, diese zu schließen!
- Nein ist es nicht, aber beenden tut süßer Kerl, der alle, so dass immer die Statik und Faden einheimischen gesäubert ist eine große Verbesserung.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Es ist allgemein als gute Praxis, dass alle Ausnahmen propagieren durch
main
. Dies ist in Erster Linie, weil Sie sicher sein können, dass der stack korrekt abgewickelt und alle Destruktoren aufgerufen werden (siehe diese Antwort). Ich denke auch, es ist mehr organisiert, Dinge zu tun, auf diese Weise; Sie wusste immer, wo Sie Ihr Programm beendet (es sei denn, das Programm stürzt ab). Es erleichtert auch die weitere konsequente error reporting (ein Punkt, der oft vernachlässigt wird in der Ausnahmebehandlung; wenn Sie kann nicht mit der Ausnahme, sollten Sie sicherstellen, dass Ihre Anwender genau weiß, warum). Wenn Sie beginnen immer mit diesem Basis-layoutdann wirst du nicht viel falsch machen. Sie können (und sollten) auch spezifische
catch
Aussagen für eine bessere error-reporting.Ausnahmen, wenn multithreading
Es gibt zwei grundlegende Arten von asynchron ausgeführten code in C++11 standard-Bibliothek features:
std::async
undstd::thread
.Zuerst die einfache.
std::async
zurückstd::future
dem erfassen und speichern keine nicht abgefangene Ausnahmen, die in der gegebenen Funktion. Aufrufstd::future::get
auf die Zukunft führt dazu, Ausnahmen zu propagieren und in die aufrufende thread.Auf der anderen Seite, wenn eine Ausnahme in einer
std::thread
Objekt nicht erfasst wird, dannstd::terminate
werden genannt:Eine Lösung könnte sein, passieren eine
std::exception_ptr
in diestd::thread
Objekt, das Sie übergeben können, die Ausnahme:Obwohl eine bessere Möglichkeit ist die Verwendung
std::package_task
:Aber es sei denn, Sie haben guten Grund für die Verwendung
std::thread
lieberstd::async
.std::packaged_task
für den Transport von Ausnahmen über thread-Grenzen hinweg. Keine Notwendigkeit, das Rad neu erfinden hier.Es ist nichts falsch mit dem fangen nicht behebbarer Fehler und das Herunterfahren Ihres Programms auf diese Weise. In der Tat, es ist, wie Ausnahmen verwendet werden soll. Achten Sie jedoch darauf, nicht über die Linie der Verwendung von exceptions zur Steuerung des Programmablaufs in normalen Umständen. Sie sollten immer einen Fehler darstellen, die nicht ordnungsgemäß behandelt, auf der Ebene der Fehler aufgetreten ist.
Aufrufen
exit()
würde nicht entspannen Sie den Stapel von dort, wo Sie es nannte. Wenn Sie möchten, um zu beenden sauber, was Sie bereits tun, ist ideal.Sie bereits akzeptiert haben, eine Antwort, aber ich wollte noch etwas dazu:
Können Sie Anruf beenden, aber (wahrscheinlich) nicht.
std::exit
reserviert werden soll für Situationen, in denen Sie zum Ausdruck bringen wollen "Ausstieg jetzt!", nicht einfach nur "Anwendung hat nichts zu tun".Als ein Beispiel, wenn Sie schreiben, eine Steuerung für einen laser verwendet in der Behandlung von Krebs, Ihre erste Priorität in dem Fall, dass etwas schief ging, wäre ein Herunterfahren der laser-und call -
std::exit
- oder vielleichtstd::terminate
(um sicherzustellen, dass alle Nebenwirkungen einer hängenden, langsam oder Absturz der Anwendung nicht zu töten, ein patient).Ähnlich wie die Ausnahmen sollten nicht verwendet werden für die Steuerung von Anwendung fließen,
exit
sollte nicht verwendet werden, um die Anwendung zu beenden unter normalen Bedingungen.Ja. Dies ist der Grund für die Verwendung von Ausnahmen. Ein Fehler ist aufgetreten, tief in den code, und etwas auf einer höheren Ebene zu behandeln. In Ihrem Fall, auf höchstem Niveau.
Gibt es Argumente für/gegen Ausnahmen vs. Fehler-codes, und dies ist gut zu Lesen:
Ausnahmen oder Fehler-codes
Können Sie, aber Sie können am Ende duplizieren der logging-code. Auch, wenn Sie in Zukunft entscheiden, dass Sie möchten, um eine Ausnahme behandeln anders, Sie haben alle Ihre exit-Aufrufe. Stellen Sie sich vor, wollte eine andere Meldung, oder fallen zurück auf ein Alternatives Verfahren.
Einer anderen, ähnlichen Frage:
Korrekte Verwendung von exit() in c++?
Haben Sie auch einen Fehler in Ihrem Ansatz, als Sie nicht behandeln, alle (C++) Ausnahmen. Sie wollen so etwas wie dieses:
Wenn Sie nicht behandeln, alle* Ausnahmen, die Sie haben könnten, das Spiel zu beenden, ohne dass Sie etwas sinnvolles.
Können Sie nicht behandeln ALLE Ausnahmen. Finden Sie unter diesem link:
C++ abfangen aller Ausnahmen
Aus der Dokumentation:
Normalen Beendigung des Programms führt die folgenden (in der gleichen Reihenfolge):
Objekte im Zusammenhang mit dem aktuellen thread mit thread Lagerung Dauer zerstört werden (C++11).
Objekte mit statischen Speicher Dauer zerstört werden (C++) und registrierten Funktionen, die mit atexit aufgerufen werden.
Alle C-streams (öffnen mit Funktionen ) sind geschlossen (und geleert, wenn gepuffert), und alle Dateien erstellt mit tmpfile entfernt werden.
Die Kontrolle wird zurück an die host-Umgebung.
Beachten Sie, dass Objekte mit automatischer Speicherung werden nicht zerstört durch Aufruf von exit (C++).
Wenn status ist null oder EXIT_SUCCESS, einen erfolgreichen Abschluss status zurückgegeben wird, die host-Umgebung.
Wenn status ist EXIT_FAILURE, eine erfolglose Beendigung status zurückgegeben wird, die host-Umgebung.
Andernfalls wird der status zurückgegeben wird, hängt von der system-und library-Umsetzung.
Für eine ähnliche Funktion, die nicht für die Bereinigung oben beschrieben, siehe quick_exit.