Kerli hat geschrieben:Aber da man in C++ alles meistens in Klassen hat, kann man die mit new angeforderten Speicherbereiche im Destruktor wieder freigeben lassen.
Code: Alles auswählen
DemoClass *demo;
try
{
demo = new DemoClass();
demo->run();
}
catch(std::bad_alloc&)
{
delete demo;
}
In diesem Beispiel ist das ganze mit Exceptions doch sehr schön gelöst. Weil was würdest du machen, wenn jetzt im Konstruktor der Klasse und in der Methode 'run()' Speicher mit 'new' angefordert wird, und das fehlschlägt. Also mir fällt keine schöne Möglichkeit ohne Exceptions ein.
Wie willst Du eine Meinung vertreten, ob etwas besser ist, wenn Du aus mangelnden Wissen nichtmals keine Wahl hast?
Nichts für ungut, aber Dein Beispiel ist keine schöne Lösung, sie ist sogar falsch. Wenn ich Lust hätte, könnte ich jetzt anfangen Fragen zu stellen und solange Du nicht nachdenkst, dokterst Du da zwei, drei weitere falsche Lösungen zurecht.
Warum gibst Du den Speicher im catch-Bereich frei? Wenn Du keinen Speicher bekommen hast, wieso gibst Du ihn frei? Dafür gibst Du ihn nicht frei, nachdem run() erfolgreich gelaufen ist.
Deine Schöne Lösung hat so einige Schönheitsfehler. Wenn Du eine bad_alloc bekommst, dann kannst Du nicht unterscheiden, ob Du nun das Objekt nicht erhalten hast, oder ob run() Mist gebaut hat. Füge das doch bitte mal hinzu, so dass Du das unterscheiden kannst. So sieht das ohne Exceptions aus.
Code: Alles auswählen
DemoClass * demo;
demo = new (std::nothrow) DemoClass();
if( demo )
if( demo->run() ) printf( "Success\n" );
else printf( "Failed\n" );
else printf( "No Memory\n" );
delete demo;
Meine Version gibt übrigens den Speicher auch dann frei, wenn er Speicher bekommen hat... sie liefert viel genauere Informationen und sie ist schon jetzt kürzer als die Exceptions-Version.
Schreib mal Deine Exceptionsversion dazu und sag mir dann was Du persönlich als übersichtlicher empfindest.
Kerli hat geschrieben:Natürlich gibt es solche Fälle auch, aber nimm zb einmal 'sqrt'.
SUPER!!!, dass Du grade sqrt nimmst, ich nehme das auch immer als Beispiel, um aufzuzeigen, wie scheiße Exceptions sind, aber dann heißt es immer, dass das Beispiel ja schlecht gewählt wäre...
Kerli hat geschrieben:Hier bekommst du im Fehlerfall einen speziellen Wert als Rückgabewert, und da wäre es doch mit Exceptions viel schöner, als wenn du immer überprüfen musst ob der Rückgabewert gültig ist.
Okay, dann machen wir mal... Damit eine Exception kommen kann, muss sie geworfen werden, also muss sqrt() immer prüfen, ob ein positiver Wert übergeben wurde then rechnen else throw Exception.
Die Alternative wäre, ich prüfe, ob mein Wert negativ ist, gebe ich einen negativen Wert ein, erhalte ich ein schwachsinniges Ergebnis von sqrt.
Wenn ich prüfe, weiß ich, dass negative Werte möglich sind, kann vor sqrt() eingreifen und den Algorithmus z.B. mit x = -x; korrekt ablaufen lassen. Okay, dafür muss ich wissen, was ich da programmiere... Wenn da der Exceptionprogrammierer auch denken muss, dann prüft er aber zweimal, also eine Überprüfung ist total für den Arsch... zusätzlich hantiert er laufend mit try rum, das kostet auch noch Rechenzeit.
Nehmen wir mal ein Beispiel, wo es nicht so um Effizients ankommt, zum Beispiel 3D Berechnungen. Da nehmen wir einen 3D Vector und wollen die Länge wissen. Für unsere Kleineren und die, denen die Vektorrechnung grade abhanden gekommen ist:
Vektorlänge = sqrt( x*x + y*y + z*z );
Multipliziert man zwei positive Zahlen, kommt was positives raus, sind beide Zahlen negativ kommt was positives raus. Addiert man positive Zahlen, kommt auch was positives raus. In diesem Algorithmus kann und da kannst Du Dich auf den Kopf stellen, es kann NIEMALS eine negative Zahl in sqrt() reingehen. Während ich mich also um gar nichts kümmeren muss, wirfst Du erstmal Rechenzeit raus in dem Du mit 'try' anfängst (ja, diese Anweisung kostet...) und anschließend stellst innerhalb von sqrt() eine vollkommen sinnlose Frage, nämlich, ob der Parameter vielleicht negativ ist, und in Java schreibst Du zusätzlich noch
zwangsweise eine Fehlerbehandlung für eine Fehler, der - ich erwähnte es bereits - NIEMALS kommen kann.
Entwickler kosten ja nix, die haben ja sonst nix zu tun und ich weiß nicht, ob absolut sinnentleerter Code für Fehlerbehandlungen die Übersicht verbessert.
Hast Du nun mehrere sinnlose Fehlerabfragen, hat ein Entwickler die Schnauze voll, weil da auf einmal fünf, sechs sinnfreie catch( bla ) {} stehen und fasst das ganze in catch( Exception ) {} zusammen. Alles, was kommen kann, wird ja davor behandelt... dummerweise kommt in der nächsten Version wieder was neues, was sich dann in catch( Exception ) {} verliert und für totale Verwirrung sorgt. Es kommt ja keine Exception, aber leider stimmt die Rechnung auch nicht.
Im Idealfall stimmt die Rechnung fast, weil nur ein kleiner Teil der Rechnung Ärger machte... Kennst Du diese Werbung, wo die beiden Brückenteile von beiden Ufern aus gebaut werden und die beiden Teile passen in der Mitte des Flusses auch fast zusammen.
DAS ist Fehlerbehandlung mit Exceptions in der Realität.
Zurück zum sqrt() Problem: Zum Glück wissen wir, dass für 3D Berechnungen große Rechner angeschafft werden und da sind die paar Takte vermutlich nicht erwähnenswert, wo sie ja nur in einer der absolut grundlegendsten Funktionen verschwendet werden.
Kerli hat geschrieben:Xin hat geschrieben:Das ist, was realistisch mit Exceptions passiert. Nichts.
Das kommt natürlich auf den Programmierer an.
Nein, das kommt nicht eben nicht auf DEN Programmierer an, sondern es kommt auf alle Programmierer in einem Projekt an. Wenn einer von x Programmierern Exceptions nicht sauber ausformuliert und wenn Du das das Popelsbeispiel da oben sauber ausformuliert hast, dann wirst Du verstehen, dass richtige Algorithmen so gut wie nie sauber in Exceptions ausformuliert werden, also wenn ein Programmierer von X das schleifen lässt, dann war es das. Dann ist's vorbei. Dann kommt irgendwo eine Exception vorbeigeflogen, mit der ein anderer Programmierer nichts anfangen kann, also was soll er tun? Er reicht sie weiter und der nächste Programmierer kann nichts damit anfangen. Nicht selten landet sie dann wie oben beschrieben in irgendeinem catch( Exception e ) {}. Kurz: Fehler behoben, Lösung vorhanden... gut vielleicht nicht für das gestellte Problem, aber das Programm verrät dieses Detail es bestimmt keinem mehr.
Du hast keine Ahnung, woher bad_alloc bei Dir im Beispiel fliegt, Du befindest Dich in Deinem catch Block absolut im Blindflug und nennst das auch noch eine schöne Lösung. Ich verstehe die Idee hinter Exceptions und sie ist gut. Aber vor allem sind Exceptions ein Konzeptproblem, denn sie helfen nicht die Fehlerhandhabung zu verbessern, sondern sie öffnen Scheunentore, um sie zu vermurksen.
Die Haupterrungenschaft, die Exception geleistet haben ist dass das Programm nicht einfach so abschmiert, sondern vorher ein PopUp-Fenster aufgeht, dass erklärt, dass das Programm abgeschmiert ist, meine Daten im Arsch sind - tut uns leid - und ich das Programm mit 'Ok' nun beenden kann.
Unter'm Strich ist genau das die Leistung, die Exceptions bringen. Eine Abnahme der Fehlerbehandlung, weil sie zu aufwendig wird und eine absolut zynische Meldung an den Benutzer.
Kerli hat geschrieben:Xin hat geschrieben:Kerli hat geschrieben:Damit man weis woher ein Fehler kommt, kann man ja sonst auch noch trace backing einbauen, was mit C bzw. ohne Exceptions nur mit viel Mehraufwand möglich wäre.
Und was machst Du mit dem Backtrace? Dem User um die Ohren werfen, weil zu retten ist da nix.
Und den Stacktrace, den habe ich auch, wenn ich's einfach knallen lasse.
Naja, eher in ein Logfile schreiben, weil wenn du weist woher ein Fehler kommt ist es viel einfacher die Ursache dafür zu finden.
Dein und mein Porgramm sind weiterhin buggy und wir haben beide einen Stacktrace, nur Deins läuft langsamer. Wo genau ist jetzt der Vorteil bei den Exceptions?
Ganz ehrlich... ich halte nix von Exceptions, weil die keiner sauber ausprogrammieren will - siehe Dein eigenes Beispiel oben - und laufend erzählen mir die Leute, wie toll die sind. Dann lese ich in Effiziente C++ Programmierung die Kapitel zu Exceptions und sehe, was die an Rechenzeit verschwenden.
In meinen Augen, eine gut gemeinte Entwicklung, die leider in die falsche Richtung ging.
Ähnlich mit dem Operator-Prioritäten von | und ==. Die Idee war gut - aber die Idee, die die Sprachentwickler hatten, hat die Entwickler nicht interessiert und seitdem ärgert sich eine Generation nach der anderen, weshalb man die Prioritäten so bescheuert ausgelegt hat, dass man immer Klammern drumrumsetzen muss. Die Operatoren werden nämlich in der Regel für andere Dinge benutzt, als Kerningham und Ritchie vermutet hatten. Dumm gelaufen.
Exceptions sind Ausnahmen, aber sie werden nicht in Ausnahmen verwendet, ihre Verwendung ist - grade in Java - die Regel. Und da hakts.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.
Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.