Wie Programm verlassen, wenn kein Parameter zurückgegeben werden darf?
-
Nö, Exceptions sind hier immer noch die saubere Lösung.
Nenne mir bitte die Begründung warum deiner Meinung nach hier das Werfen einer Exception angebracht wäre, dann kann ich dir sagen wo du den Denkfehler machst.
BTW: wenn du eine Exception wirfst und nirgends fängst werden auch keine Destruktoren mehr abgearbeitet. Was auch gut so ist.
-
heine789 schrieb:
Die Funktion darf auch nicht verändert werden.
dann ruf diese funktion nur von einer anderen auf, die vorher 'currentnode' checkt. allein davon ist's ja abhängig ob's klappt oder nicht ...
-
Man hat aber die Möglichkeit per Exceptionhandling darauf zu reagieren. Wer das nicht will lässt es einfach.
Zudem kann es durchaus sein das Klassen anderer Bibliotheken darauf angewiesen sind das ein Destruktor aufgerufen wird. Lockfiles werden wohl nicht gelöscht, fremde Tasks die man fernsteuert nicht geschlossen.
Mit werfen der Exception gebe ich so dem Anwender der Klasse/Funktion die Möglichkeit zu reagieren. Mit einem exit lasse ich einfach Möglichkeiten weg das Problem sauber zu lösen und riskiere das unbekannte Resourcen nicht aufgeräumt werden.
-
Plotzenhotz schrieb:
Nenne mir bitte die Begründung warum deiner Meinung nach hier das Werfen einer Exception angebracht wäre, dann kann ich dir sagen wo du den Denkfehler machst.
Vielleicht ist ne Datei geöffnet? Vielleicht steht schon was im Buffer? Vielleicht geht deine config-Datei flöten?[/quote]
-
Ok.
Vorweg ein paar Kleinigkeiten. Diverse Files (File-Handles meine ich), Speicher, sonstige Resourcen (Sockets, ...) werden normalerweise wenn ein Prozess terminiert vom OS aufgeräumt, darum braucht man sich keine Sorgen zu machen. Diverse Temp-Files bleiben dabei natürlich auf der Platte stehen wenn sie nicht in einem "lösch mich wenn das Handle zugemacht wird" Modus geöffnet waren. Soviel dazu. Weiters sollte man wissen dass das Stack-Unwinding nur dann passiert wenn die Exception auch irgendwo gefangen wird. Wird sie nicht gefangen wird der Prozess einfach so terminiert - macht dann auch keinen Unterschied mehr.Nu zu dem Grund warum ich meine dass es in Fällen wo man eine Precondition verletzt sieht schlauer ist das Programm einfach abzubrechen, und zwar ohne Stack-Unwinding. Einfache Antwort: eben genau weil dann kein Stack-Unwinding mehr passiert, also keine Destruktoren mehr laufen.
Destruktoren auszuführen hat nur dann einen Sinn wenn man davon ausgeht dass das Programm noch in einem gültigen Zustand ist. Da aber eine Precondition verletzt wurde heisst das es liegt ein Programmierfehler vor. Wo dieser Fehler genau liegt können wir nicht wissen, der kann direkt in der aufrufenden Funktion liegen, oder in einem ganz anderen Modul. Demzufolge können wir auch nicht wissen was dieser Fehler noch angerichtet hat - d.h. wir können nichtmehr garantieren dass das Programm noch in einem gültigen Zustand ist. In der Situation das Programm noch irgendwie fortzusetzen (und Destruktoren ausführen hiesse das Programm fortsetzen) kommt einem Pokerspiel gleich.Daher macht es IMHO mehr Sinn das Programm einfach abzubrechen.
Der Denkfehler liegt also IMHO darin anzunehmen es sei sicher noch irgendwelchen Code auzuführen wenn ein unbekannter Fehler dazu geführt hat dass ein Ereignis eingetreten ist welches per definitionem nie eintreten darf.
-
Wäre die Schlussfolgerung dann nicht, das Exceptions völlig überflüssig sind und es generell besser wäre terminate zu verwenden ? Warum verwendet das .Net Framework Exceptions , oder die std lib ?
Wo ist bei der Schlussfolgerung der Denkfehler ?
-
Knuddlbaer schrieb:
Wäre die Schlussfolgerung dann nicht, das Exceptions völlig überflüssig sind und es generell besser wäre terminate zu verwenden ?
nö, exceptions sind schon gut, jedenfalls wenn man sofort drauf reagiert. kommt das 'catch' zu weit oben kann man u.u. den schaden nicht mehr begrenzen und muss dann das programm beenden um schlimmeres zu vermeiden...
-
Ich bekomme gedanklich ebend in diesem Zusammenhang das geschriebene von Plotzenhotz nicht zusammen , würde es jedoch gerne verstehen.
Ich würde mich freuen, wenn Plotzenhotz sich hierzu noch mal äußern könnte, da man gerade bei gegensätlichen Meinungen oft viel lernen kann.
-
Der OP kann keine exceptions fangen. Ergo ist das werfen einer Exception Aua.
-
Hm, kann ich nix mit anfangen
-
Plotzenhotz schrieb:
...Weiters sollte man wissen dass das Stack-Unwinding nur dann passiert wenn die Exception auch irgendwo gefangen wird....
Das höre ich zum ersten Mal !!! Glaube es auch und habe es gerade ausprobiert (gcc 3.4.4). 
GUUUT zu wissen - und seltsam, daß es mit bislang in meinem der "Expertbücher" begegnet ist. Außerdem schwer abgefahren: Ich dachte immer, Stackunwinding sei Bestandteil ein fertig compilierten Moduls. Anscheinend stellt ein Modul aber nur "Informationen" zur Verfügung, mit denen das gelinkte Modul das dann durchführen kann...
Ich muß mir da noch ein paar Gedanken drüber machen ...Einerseits finde ich Deine Ausführungen recht logisch (aus individueller Entwicklersicht), andererseits aber auch (aus "Gesamtsystemsicht") für zu kurz gesprungen.
- Wenn der Programmzustand "vermurkst" ist .... was könnte ein ausgeführter Dtor daran noch verschlimmern ?
- in Serversystemen wirst Du massiv Ärger bekommen, wenn ein falscher Parameter (wenn man ehrlich ist: Welches größere Programm ist wirklich fehlerfrei ?) zu einem kompletten Abbruch/Restart führt.
- terminate() ist ein absolutes "no go" für Systeme, die eine retry-Strategie unterstützen sollen.
...*grübel*
Gruß,
Simon2.
-
Knuddlbaer schrieb:
Ich bekomme gedanklich ebend in diesem Zusammenhang das geschriebene von Plotzenhotz nicht zusammen , würde es jedoch gerne verstehen.
...Wenn ich das recht verstanden habe: "In bestimmten Situationen ist der Aufruf von terminate() besser als das Werfen einer exception ('besser' = zuverlässiger). Das Vertrauen auf exceptions kann einen in falscher Sicherheit wiegen."
Gruß,
Simon2.
-
Ich verstehe Plotzenhotz so, das es generell besser ist terminate zu verwenden.
-
Ich meine man sollte zwischen 'Exceptions' und 'Errors' unterscheiden. Eine Exception ist eben etwas was vorkommen kann und darf wenn das Programm 100% Fehlerfrei ist. Für so einen Fall würde ich NICHT vorschlagen terminate() aufzurufen - wäre ja komplett doof. Für den Fall allerdings dass etwas eintritt was nur passieren kann wenn das Programm eben NICHT 100% OK ist, man also einen Programmierfehler "gefunden" hat, in dem Fall wäre es oft schlauer das Programm abzuschiessen.
Viele Programmierer meinen solche Fälle sollte man in Release garnicht prüfen, dafür müsse ein assert() reichen. Was ich dann wieder etwas mutig finde.
---
Leider hat es sich eingebürgert in C++ von std::exception abzuleiten anstelle von std::runtime_error, daher kann man std::logic_error nichtmehr sinnvoll verwenden. Gäbe es eine Basisklasse std::error die nicht von std::exception abgeleitet wäre dann wäre die Sache besser, dann könnte man auch für einen 'Error' eine Exception werfen, und ein "vernünftiges" Programm würde einfach nie Errors fangen. Andrerseits ist da wieder "catch(...)" was diese Errors auf fangen würde - was auch wieder nicht gut ist.
---
Exceptions sind eine wunderbare Sache, und ich würde niemals darauf verzichten wollen. Bloss sie für jeden erdenklichen Fehler (inklusive Programmierfehlern) zu verwenden finde ich nicht gut.
-
Ah ok, dann hatte ich das missverstanden.
Vielen Dank für Deine Geduld

-
Plotzenhotz schrieb:
Ich meine man sollte zwischen 'Exceptions' und 'Errors' unterscheiden....
"Ich rieche Javafleisch !"

Nach meiner Erfahrung ist aber genau diese Unterscheidung in der Praxis das eigentliche Problem: Wann kann ich (in einer lokalen Funktion) wirklich sagen, dass eine weitere Ausführung des (gesamten) Programms keinen Sinn mehr macht ?
Ich denke, dahier kommt auch diese generelle Exceptionverwendung ... da hat ein Aufrufer wenigstens noch die Chance, meine Einschätzung zu korrigieren. Damit will ich das nicht rechtfertigen/verteidigen, sondern nur die Entstehung erklären.
Gruß,
Simon2.
-
Hallo
Der Vorteil von Exceptions gegenüber terminate ist aber, das eine Beschreibung des Abbruchsgrund bzw. relevantes Datenmaterial übergeben werden kann, was grad zum Debuggen sehr nützlich ist. Oder weißt du auf Aufhieb, welches deiner terminates grad einen Absturz ausgelöst hat, den der Benuter per E-Mail grad anmeckert?
bis bald
akari
-
Plotzenhotz schrieb:
Viele Programmierer meinen solche Fälle sollte man in Release garnicht prüfen, dafür müsse ein assert() reichen. Was ich dann wieder etwas mutig finde.
Dann definiert man halt nicht NDEBUG.
Leider hat es sich eingebürgert in C++ von std::exception abzuleiten anstelle von std::runtime_error
Kannst du das belegen?
-
Plotzenhotz, lol, ist klar: wenn das Laden des Plugins fehlschlaegt schiesse ich die anwendung ab. Oder wenn der User eine sonstige non-vitale operation durchfuehren will... sofort anwendung abschiessen und alle daten loeschen.
ne ne ne ne ne ne
das kann nicht dein ernst sein.
-
Shade Of Mine schrieb:
Plotzenhotz, lol, ist klar: wenn das Laden des Plugins fehlschlaegt schiesse ich die anwendung ab. Oder wenn der User eine sonstige non-vitale operation durchfuehren will... sofort anwendung abschiessen und alle daten loeschen.
ne ne ne ne ne ne
das kann nicht dein ernst sein.
Das ist natürlich Unsinn und hat er auch so nicht gesagt. Er hat ganz richtig darauf hingewiesen, wie eine Unterscheidung in Fehlerzustände die unmittelbar durch Programmierfehler zurückzuführen sind, und solche die unvermeidbar mit dem Programmablauf auftreten können, wie z.B. durch falsche Benutzereingaben oder ähnliches.In ersterem Fall (den er mit dem Label "Error" bezeichnet hat, nicht zu verwechseln mit einem Fehlercode beim Aufruf einer Systemfunktion) sollte das Programm in der Tat nicht weiterlaufen, denn die Erfahrung zeigt, dass dadurch kritische Fehler versteckt werden und u.U. noch schlimmere Folgen möglich sind.
Der andere Fall (den er mit dem Label "Exception" versehen hat), also Fehlersituationen die ohne Programmiererverschulden im normalen Lebensalltag des Programmes auftreten können, sind hingegen eine gute Anwendung für Exceptions (wenn man sich dann auch antrainiert, exceptionfest zu programmieren, was leider nicht so verbreitet ist).
Daher hoffe ich doch sehr, das es sein Ernst war.

Wenn es Dir nur um die verwendeten "Label" ging, wäre das ein anderer Diskussionspunkt, der aber den Rat als Solches nicht unnütz macht.