Wie Programm verlassen, wenn kein Parameter zurückgegeben werden darf?
-
na mit exit(0) natürlich
-
Keine gute Idee in C++, da dtors nicht mehr abgearbeitet werden.
-
groovemaster schrieb:
Bis du dich in Exceptions eingearbeitet hast, kannst du auch erstmal einen Dummy zurückgeben.
template<class KeyType, class ValueType> ValueType& DictionaryAsHashTable<KeyType, ValueType>::get() { static ValueType dummy; // notfalls noch entsprechend initialisieren if(currentNode != NULL) return currentNode->value; else { cerr << "Fehler: Eintrag nicht vorhanden!" << endl; return dummy; } }Später solltest du hier natürlich Exceptions verwenden.
Und wie bekommt er mit das der Dummy garkein korrektes Objekt ist?
-
Hmm, würds zwar persönlich nicht machen, aber vielleicht so:
static ValueType dummy; ... ValueType& MyFunc () { ... return dummy; } ... ValueType& result = MyFunc(); if(&result == &dummy) ...Sollte imho funktionieren.
MfG SideWinder
-
Hm, gibts hier eine gewisse Abneigung gegen Zeiger? Wenn er schon keine Exceptions verwenden darf/kann ist die Rückgabe eines Zeigers doch wohl recht naheliegend. Man muss Zeiger nicht auf Teufel komm raus vermeiden.
grüße
-
Ach was, ne Referenz kann man mit Gewalt doch auch auf 0 verbiegen

-
Wenn der Fall einen Programmierfehler darstellt und du keine Exception werfen kannst/darfst, dann nimm abort(). abort() ist genau für solche "hab nen Fehler gefunden den ich nicht behandeln kann (will)" Fälle gemacht. Vor Beenden des Programmes wird dabei üblicherweise noch eine Fehlermeldung angezeigt die besagt dass irgendwas böses passiert ist womit das Programm nicht umgehen kann (oder so ähnlich). Destruktoren werden auch keine mehr abgearbeitet (also kein Stack-Unwinding wie man es beim Werfen einer Exception hätte), was aber normale überhaupt kein Problem darstellt, da moderne Betriebssysteme schön hinter einem terminierten Prozess aufputzen, also alle Files/Devices/Sockets... zumachen/freigeben etc. Dass keine Destruktoren mehr laufen ist sogar oft ein Vorteil, da man in manchen Situationen vor dem "jetzt häng' ich mich weg" Statement (abort, throw, was auch immer) garnicht sicherstellen kann dass alle Invarianten wieder hergestellt sind. Und wenn ein Destruktor läuft während nicht alle Invarianten erfüllt sind kann das böse Folgen haben.
Einfach nur nix tun und einen Defaultwert zurückzugeben ist so ziemlich Das Dümmste Was Man Tun Kann (tm).
Ahja, auf keinen Fall bitte exit(0) verwenden - der Returncode 0 wird eigentlich immer als "alles OK" angesehen, wenn schon exit dann exit(1) oder irgendwas bloss nicht 0.
-
David_pb schrieb:
Und wie bekommt er mit das der Dummy garkein korrektes Objekt ist?
Indem er eine Exception wirft. :p
Nicht so verbissen sehen, war ja nur als Übergangslösung gedacht. Und hat den Vorteil, dass wo jetzt kein Fehlerhandling gemacht werden kann, auch später kein Fehlerhandling stattfindet. Das Exceptionhandling erfogt separat von der eigentlichen Codesequenz.David_pb schrieb:
Hm, gibts hier eine gewisse Abneigung gegen Zeiger?
Ja, gibt es.
heine789 schrieb:
Die Funktion darf auch nicht verändert werden.
-
heine789 schrieb:
Im else-Fall kann kein Parameter zurückgegeben werden. Man darf es auch nicht.
Die Funktion darf auch nicht verändert werden.In diesem Fall soll das Programm beendet werden. Welche einigermaßen saubere Lösung gibt es dafür?
Die Vorgabe ist doch ganz klar, oder? Ich sehe zumindest keine Möglichkeit wie da Exceptions oder Dummy-Werte helfen sollen.
Die IMHO einzig richtige Antwort heisst im übrigen nicht wie ich zuerst fälschlicherweise geschrieben habe abort() sondern -> terminate() <-. Man verzeihe mir den Patzer

terminate() tut zwar normalerweise auch nixe ausser abort() aufzurufen, aber man kann den terminate-handler auf eine eigenen Funktion verbiegen, und die Möglichkeit wollen wir dem Programm ja nicht nehmen.
-
Nö, Exceptions sind hier immer noch die saubere Lösung.
-
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