Exceptions, verstehe den Ablauf noch nicht so ganz
-
Stellt euch mal ungefähr so einen Funktionsablauf vor:
(nur ganz grob mal)void f(int a) { ........ ...... if(a == 19) { throw runtime_error("Benzin läuft aus!"); } else { cout << "CHECK: Okay!" << endl; } ...... ....... } void g(int b) { ...... ...... f(19); ....... ...... } void j(int c) { ...... ....... g(23); ....... ........ } int main() { try { j(320); } catch(runtime_error err) { cout << err.what() << endl; ..... ....... } return 0; }Wenn nun in Funktion f wirklich eine Ausnahme geworfen wird, was passiert dann genau? Wird die Funktion g sofort abgebrochen? Oder läuft es die Funktion trotzdem noch durch? Wird g und j auch abgebrochen? Und es geht sofort zum Handler um den Fehler abzufangen, und dann gehts wieder zurück zu f? Kann ich mir ein "throw" wie ein "break" vorstellen des erstmal abbricht?..........
Könnt ihr mir den ganzen Ablauf in meinem Beispiel, mal versuchen zu erklären? Oder wenns einfacher für euch ist, könnt ihrs mir auch an nem eigenen Code-Beispiel von euch selbst erklären?!
MfG
Stromberg
-
Wenn du eine Exception wirfst, fliegt sie solange, bis sie gefangen wird. Wird sie nicht gefangen, bringt sie das Programm zum Absturz.
In deinem Beispiel wird die Funktion
f()beimthrow-Statement unmittelbar verlassen. Der Rest der Funktion wird nicht mehr ausgeführt, nach der Fehlerbehandlung kehrt das Programm auch nicht dahin zurück. In den Funktioneng()undj()passiert nichts, da fliegt die Exception ungehindert durch. Erst inmain()fängst du sie ab, wodurch du in dencatch-Block gelangst.Ich würde die Exception übrigens eher als Referenz auffangen:
catch (std::runtime_error& err)
-
Ah, okay, also nur die funktion in der die Ausnahme geworfen wird, wird sofort beendet. Anschließende "Überfunktionen" werden jedoch ganz normal weiter durchlaufen, bis irgendwann die Ausnahme abgefangen wird. Aber wie soll ich mir so eine geworfene Ausnahme vorstellen, kann ich mir dass wie ein "2tes unsichtbares return" vorstellen, welches die Ausnahme von jeder "Unterfunktion" immer weiter in die nächst höhere "Überfunktion" returned, bis sie im try Block landet, und dann letztlich im Handler abgefangen wird? (oder dass Programm wird halt einfach abgebrochen, wenn es kein passender catch Block innerhalb des Handlers vorhanden ist.)
MfG
Stromberg
-
Stromberg schrieb:
Anschließende "Überfunktionen" werden jedoch ganz normal weiter durchlaufen, bis irgendwann die Ausnahme abgefangen wird.
Nein, auch diese werden nicht mehr weiter ausgeführt, sondern die Exception fliegt "hindurch", also ohne in der Funktion noch irgendetwas anzurichten.
Stromberg schrieb:
Aber wie soll ich mir so eine geworfene Ausnahme vorstellen, kann ich mir dass wie ein "2tes unsichtbares return" vorstellen, welches die Ausnahme von jeder "Unterfunktion" immer weiter in die nächst höhere "Überfunktion" returned, bis sie im try Block landet, und dann letztlich im Handler abgefangen wird?
Ja, könntest du dir so vorstellen. Du musst einfach wissen, dass nach der
throw-Anweisung kein Code mehr ausgeführt wird, bis du dich wieder imcatch-Block befindest.
-
Nexus schrieb:
[...]In den Funktionen
g()undj()passiert nichts, da fliegt die Exception ungehindert durch[...]Das kann man so nicht stehen lassen. Die ganzen Variablen mit automatischer Speicherdauer, die Du in
g()undj()bis zum Exception auslösenden Aufruf angelegt hast, werden wieder freigegeben. Bei komplexen Objekten bedeutet das, dass deren Destruktoren aufgerufen werden. Es wird also durchaus noch Code aufgerufen.
Das ist eine sehr wichtige Eigenschaft bei dem Mechanismus, der einem viel Arbeit bei der Ressourcenverwaltung sparen kann, wenn man ihn richtig ausnutzt. Als Stichwort für die Suchmaschine werfe ich mal RAII in den Raum.
-
Als Einstiegslektüre die einem ein wenig den Umgang und die Gefahren beim Exceptionhandling näherbringen kann empfehle ich die entsprechenden Absätze im Guru of the Week.
-
Tachyon schrieb:
Das kann man so nicht stehen lassen.
Du hast natürlich Recht, das war etwas ungenau. Vielen Dank für die Ergänzung.
-
Es passiert genau dasselbe, was auch passieren würde, wenn die Funktionen, an genau der Stelle wo die Exception "durchfliegt" mit "return" verlassen würden. Natürlich mit dem Unterschied, dass es keinen Returnwert, dafür aber eine Exception gibt.