C++0x checked exceptions?
-
exceptionalcoder schrieb:
Die Policy Methode kann auch einfach ne normale Exception werfen und die Hostklasse bekommt garnix davon mit. Nur weil es zusätzliche checked Exceptions gibt, bedeutet das ja nicht, dass es die alten nicht mehr gibt.
Wenn das optional wäre, hätte ich nichts dagegen.
-
Wie macht man eigentlich in größeren Projekten mit mehreren Programmieren richtige Fehlerbehandlung? Schreibt man da in die Doku welche Exceptions die Funktion wirft oder verwendet man Errorcodes?
-
wie gehts? schrieb:
Wie macht man eigentlich in größeren Projekten mit mehreren Programmieren richtige Fehlerbehandlung? Schreibt man da in die Doku welche Exceptions die Funktion wirft oder verwendet man Errorcodes?
Man wirft Exceptions. Und checked Exceptions sind da nicht noetig, denn es hat sich herausgestellt dass checked Exceptions zu sehr vielen
try { foo(); } catch(Exception e) {}fuehren - und das ist das schlimmste was es gibt.
Zumal es viele andere Probleme mit checked Exceptions gibt wie zB Versionierung oder eben auch ist es oft der Fall dass die entscheidung ob eine exception eine checked exception ist oder nicht vom client code zu entscheiden ist.
weiters sind exception typen in c++ sehr uninteressant: da man sowieso jede funktion mindestens exception neutral schreibt. man wuerde einfach einen enormen aufwand betreiben muessen bei templates die ganze zeit die checked exception typen durchzureichen.
und man hat eben auch in java bereits eingesehen dass checked exceptions eine nette idee sind, aber in der praxis einfach unpraktisch sind. c# ist ja nach reiflicher ueberlegung ebenfalls weg von exception spezifikationen gegangen.
denn im prinzip ist es einem in den meisten faellen sowieso egal welche exception geflogen ist. denn ob ich die datei nicht lesen kann weil sie gelockt ist, nicht da ist oder ich nicht die noetigen rechte habe sie zu oeffnen ist alles das selbe fuer mich. nur sehr sehr selten will ich das feiner unterscheiden. und da sind checked exceptions halt wieder unpraktisch.
die generelle idee ist zwar super, aber in der praxis funktioniert es nicht so wie es soll. man tauscht im endeffekt nur ein paar probleme gegen ein paar andere - anstatt wirklich probleme zu loesen.
-
@Exceptionalcoder, deine Argumente sind doch totaler Käse. Eine Flut an Warnungen führt zwangsläufig dazu, dass man den Überblick verliert, und bei jedem neukompilieren könnten neue dazukommen (und alte verschwinden - also nichts mit einfach die Anzahl merken!) und sobald du anfängst Warnungen zu deaktivieren weil es zu viel wird bestätigst du meine Behauptung.
Es gibt Compiler da muss man Warnungen abschalten, damit man überhaupt arbeiten kann (z.B. der von VC6, auch wenn der heute veraltet ist, Legacy Projekte gibts noch zu Hauf) und in dem Moment haben die Warnungen einen kontraproduktiven Effekt.Also gleich nur da warnen wo es sinnvoll ist und nicht für jede nichtgefangene Checked Exception eine Warnung generieren.
Checked Exceptions könnten allerdings sinnvoll sein, wenn man das throws-Schlüsselwort so umbaut, dass man Exceptions nicht fangen muss sondern explizit weiterwerfen kann, so würde man kurz schauen ob man die Exception behandeln kann und wenn nicht, gibt man an, dass man sie weiterwerfen will.
Ohne leere try-catch-Blöcke mit throw drin, oder ähnliche Monster.Übrigens dein Argument mit 5 Stunden irgendwas - was hat das mit der Dikussion zu tun? Eine nichtgefangene Exception würde so oder so das Programm terminieren, nur der Unterschied ist bei einer echten Anwendung wäre ganz oben zumindest ein catch-All-Block, so dass das Programm nicht auf die Böse Art endet, sondern ne schöne Fehlermeldung anzeigt und Informationen für den Fehler sammelt und abspeichert.
Und natürlich wäre weiter unten auch ein catch-Block welcher versucht die Daten noch in einer Datei zu speichern vorm Terminieren der Anwendung.Ich sehe nicht inwiefern dein Beispiel den Sinn/Unsinn von Checked Exceptions belegt.
-
Ich glaube, checked Exceptions sind ein reichlich unverstandener Mechanismus.
-
Exceptionist schrieb:
@Exceptionalcoder, deine Argumente sind doch totaler Käse. Eine Flut an Warnungen führt zwangsläufig dazu, dass man den Überblick verliert, und bei jedem neukompilieren könnten neue dazukommen (und alte verschwinden - also nichts mit einfach die Anzahl merken!) und sobald du anfängst Warnungen zu deaktivieren weil es zu viel wird bestätigst du meine Behauptung.
Es gibt Compiler da muss man Warnungen abschalten, damit man überhaupt arbeiten kann (z.B. der von VC6, auch wenn der heute veraltet ist, Legacy Projekte gibts noch zu Hauf) und in dem Moment haben die Warnungen einen kontraproduktiven Effekt.Du wolltest mit blöden Warnings anfangen, normal sind es Errors und die lenken nicht von den anderen warnings ab
Checked Exceptions könnten allerdings sinnvoll sein, wenn man das throws-Schlüsselwort so umbaut, dass man Exceptions nicht fangen muss sondern explizit weiterwerfen kann, so würde man kurz schauen ob man die Exception behandeln kann und wenn nicht, gibt man an, dass man sie weiterwerfen will.
Ohne leere try-catch-Blöcke mit throw drin, oder ähnliche Monster.Das mit throws funktioniert so wie du es willst.

Übrigens dein Argument mit 5 Stunden irgendwas - was hat das mit der Dikussion zu tun? Eine nichtgefangene Exception würde so oder so das Programm terminieren, nur der Unterschied ist bei einer echten Anwendung wäre ganz oben zumindest ein catch-All-Block, so dass das Programm nicht auf die Böse Art endet, sondern ne schöne Fehlermeldung anzeigt und Informationen für den Fehler sammelt und abspeichert.
Und natürlich wäre weiter unten auch ein catch-Block welcher versucht die Daten noch in einer Datei zu speichern vorm Terminieren der Anwendung.LOL. Wieder mal ein "Ich bin zu blöd richtige Fehlerbehandlung zu machen also sind alle Exceptions schlecht"-Argument. Das was du schreibst kann man auch mit normalen Exceptions machen.
Mal wieder nur Argumente die keine sind, sondern nur aus deinem Unwissen stammen. Das wird jetzt langsam langweilig.
-
ShadeOfMine schrieb:
wie gehts? schrieb:
Wie macht man eigentlich in größeren Projekten mit mehreren Programmieren richtige Fehlerbehandlung? Schreibt man da in die Doku welche Exceptions die Funktion wirft oder verwendet man Errorcodes?
Man wirft Exceptions....
weiters sind exception typen in c++ sehr uninteressant: da man sowieso jede funktion mindestens exception neutral schreibt. man wuerde einfach einen enormen aufwand betreiben muessen bei templates die ganze zeit die checked exception typen durchzureichen.
Was mit checked exceptions gehen würde oder nicht interessiert mich nicht, da es sie sowieso nicht gibt. Ich möchte wissen wie es jetzt umgesetzt wird.
Die stellen, die mir einfallen, an denen es sinnvoll ist exceptions zur fehlerbehandlung zu verwenden sind lese/schreibzugriffe auf datei/db/server... Wie macht ihr das da? Woher wisst ihr welche exception von welchem typ man jetzt fangen muss, schreibt ihr das in den Kommentar? Oder gebt ihr einfach NULL zurück und prüft dann auf das? Oder was macht ihr?
Die exceptions die nur für sowas wie ungültiger arrayindex da sind, sind doch nur für programmierfehler und ne sinnvolle fehlerbehandlung ist sowieso nicht möglich, oder?
-
LOL. Wieder mal ein "Ich bin zu blöd richtige Fehlerbehandlung zu machen also sind alle Exceptions schlecht"-Argument. Das was du schreibst kann man auch mit normalen Exceptions machen.
LOL. Wieder mal ein "Ich bin stur um andere Argumente zu akzeptieren also picke ich mir die raus, die ich wiederlegen kann"
Mal ehrlich, es wurde genügend Argumente genannt...
-
wie gehts? schrieb:
Die stellen, die mir einfallen, an denen es sinnvoll ist exceptions zur fehlerbehandlung zu verwenden sind lese/schreibzugriffe auf datei/db/server... Wie macht ihr das da? Woher wisst ihr welche exception von welchem typ man jetzt fangen muss, schreibt ihr das in den Kommentar? Oder gebt ihr einfach NULL zurück und prüft dann auf das? Oder was macht ihr?
Die exceptions die nur für sowas wie ungültiger arrayindex da sind, sind doch nur für programmierfehler und ne sinnvolle fehlerbehandlung ist sowieso nicht möglich, oder?
Jede Art von Laufzeitfehler ist eine Exception.
Es gibt 2 Arten von Fehlern: Logische und Laufzeitfehler.Logische Fehler sind zB einen null zeiger an ein fstream Objekt zu geben um es zu oeffnen. Oder ein div by zero fehler.
Alles was in einem fehlerfreien programm nicht auftreten kann ist ein logischer fehler - oder statischer wenn man so will.
Laufzeitfehler sind dann alles andere: zB datei wurde nicht gefunden, verbindung zur datenbank wurde abgebrochen. nicht genug speicher vorhanden, etc.
errorcodes sind nur dann sinnvoll wenn man keine exception verwenden kann (zB weil es ueber binary grenzen hinaus geht).
-
Shade Of Mine schrieb:
wie gehts? schrieb:
Die stellen, die mir einfallen, an denen es sinnvoll ist exceptions zur fehlerbehandlung zu verwenden sind lese/schreibzugriffe auf datei/db/server... Wie macht ihr das da? Woher wisst ihr welche exception von welchem typ man jetzt fangen muss, schreibt ihr das in den Kommentar? Oder gebt ihr einfach NULL zurück und prüft dann auf das? Oder was macht ihr?
Die exceptions die nur für sowas wie ungültiger arrayindex da sind, sind doch nur für programmierfehler und ne sinnvolle fehlerbehandlung ist sowieso nicht möglich, oder?
Jede Art von Laufzeitfehler ist eine Exception.
Es gibt 2 Arten von Fehlern: Logische und Laufzeitfehler.Logische Fehler sind zB einen null zeiger an ein fstream Objekt zu geben um es zu oeffnen. Oder ein div by zero fehler.
Alles was in einem fehlerfreien programm nicht auftreten kann ist ein logischer fehler - oder statischer wenn man so will.
Laufzeitfehler sind dann alles andere: zB datei wurde nicht gefunden, verbindung zur datenbank wurde abgebrochen. nicht genug speicher vorhanden, etc.
errorcodes sind nur dann sinnvoll wenn man keine exception verwenden kann (zB weil es ueber binary grenzen hinaus geht).
Das ist die Theorie. Mich interessiert die Praxis. Wie macht ihr das zum Beispiel beim speichern? Wenn z.B. eine Datei auf Festplatte gespeichert werden soll und der User wählt ein schreibgeschützes Laufwerk. Was macht ihr dann? Man wählt in der GUI über nen File Dialog ne Datei aus. Dann wird ne save Methode aufgerufen und die kann fehlschlagen. Last ihr jetzt die save Methode ne exception werfen und wenn ja, woher weiß der GUI Programmierer welche? Oder was macht ihr?
-
wie gehts? schrieb:
Oder was macht ihr?
ja, eine exception fliegt.
was ist daran komisch oder verwirrend?natuerlich wird die exception auch wieder gefangen.
was genau willst du wissen oder wie genau stellst du dir programmieren vor? dass man fehler einfach ignoriert oder wie?
-
Toni, es ging dem Fragesteller glaube ich nicht um die Ausnahme, sondern darum, wie man sie kommuniziert.
Und die Antwort lautet: In Projekten, in denen ich bisher mitgearbeitet habe, wurde das durch die Dokumentation erreicht.
-
Konrad Rudolph schrieb:
Toni, es ging dem Fragesteller glaube ich nicht um die Ausnahme, sondern darum, wie man sie kommuniziert.
Und die Antwort lautet: In Projekten, in denen ich bisher mitgearbeitet habe, wurde das durch die Dokumentation erreicht.
Genau sowas will ich wissen. Gibts noch andere Lösungen als in die Doku schreiben?
-
Theoretisch kannst du Exceptionspezifikationen (so heißen die glaub ich, man möge mich korrigieren wenn's nicht so ist) benutzen:
void do_some_risky_stuff () throw (risky_exception, stuff_exception);Das bewirkt nicht nur das der Anwender weiß „Aha, es fliegen möglicherweise folgende Exceptions“, es setzt sogar zwingend fest, dass /nur/ diese Exceptions geworfen werden dürfen.
Allerdings sind die böse, weil extrem fies zu implementieren. Einige Compiler ignorieren sie völlig, bei anderen bricht die Performance ein. In normalen C++-Programmen wird deshalb nur throw () verwendet, was garantiert, dass die Funktion keine Exception wirft.
Was man aber häufiger sieht ist etwas der Formvoid do_some_risky_stuff () // throw (risky_exception, stuff_exception);
-
.filmor schrieb:
es setzt sogar zwingend fest, dass /nur/ diese Exceptions geworfen werden dürfen.
Allerdings durch *Laufzeit*abfragen. D.h. es ist sehr wohl auch möglich, andere Ausnahmen zu schmeißen, allerdings wird dann 'unexpected' aufgerufen und das Programm beendet.
/EDIT: Details ausgelassen. Beispiel gibt's hier: http://cpptruths.blogspot.com/2007/05/use-of-stdbadexception.html
-
.filmor schrieb:
Das bewirkt nicht nur das der Anwender weiß „Aha, es fliegen möglicherweise folgende Exceptions“, es setzt sogar zwingend fest, dass /nur/ diese Exceptions geworfen werden dürfen.
Allerdings sind die böse, weil extrem fies zu implementieren.Die Implementation ist weniger wesentlich (zwar werden Exceptionspezifikationen heute gerne ignoriert, aber nur, weil sie sich bereits als nicht nützlich genug erwiesen haben). Das Problem ist tatsächlich die Semantik:
Eine Exceptionspezifikation bestimmt - wie richtig gesagt wurde - dass die betreffende Funktion nur diese Exceptions werfen darf. Sie bestimmt aber nicht, dass diese Funktion nur solche Exceptions werfen wird oder kann. Letzteres erlaubte es uns, Funktionen an kritischen Stellen einzusetzen, wo Fehlschläge nicht oder nur unter bestimmten definierten Bedingungen erlaubt sind; ersteres ist im Grunde nicht besonders nützlich: das ist nicht wesentlich anders als ein automatisches catch(A){throw;}catch(B){throw;}...{catch(...){terminate();} um jeden Funktionsaufruf.Nun kenne ich Java nicht - ich kann dem hier vorgebrachten Vorschlag aber nicht entnehmen, welche Semantik für checked exceptions gelten soll. Im Übrigen ist es auch kein Zufall, dass Exceptionspezifikationen diese weniger nützliche Semantik haben: etwas anderes ist schlicht technisch unmöglich. Wenn sich eine Funktionsimplementation darauf beschränken soll, dass nur andere Funktionen mit gleichermaßen oder stärker eingeschränkten Spezifikationen aufgerufen werden dürfen, so ist das zu einschränkend um nützlich zu sein: denn gerade den wichtigen Fall, dass wir eine Funktion schreiben, die von vornherein nicht für alle Teile erfolgreich sein muss, wird so nicht erfasst:
bool write_file(...) { try { write(); } catch(...) {return false;} return true;Diese Funktion könnte eine leere Exceptionspezifikation haben, für write ist das nicht der Fall. Erlaubt man aber den Aufruf von Funktionen mit weniger eingeschränkten Spezifikationen, so ist es im Allgemeinen (von catch(..) abgesehen) nicht beweisbar, dass die enthaltenen catch-Klauseln alle möglichen Fälle abdecken.
-
camper schrieb:
Die Implementation ist weniger wesentlich (zwar werden Exceptionspezifikationen heute gerne ignoriert, aber nur, weil sie sich bereits als nicht nützlich genug erwiesen haben).
Meine da mal was gelesen gehabt zu haben. Scheinbar schalten manche Compiler das Inlining bei solche Funktionen ab oder setzen es als
try { func(); } catch (erlaubte_exception& e) { throw; } catch (...) { unexpected (); }um.
Ich glaub es war dieser Artikel.
-
camper schrieb:
Nun kenne ich Java nicht - ich kann dem hier vorgebrachten Vorschlag aber nicht entnehmen, welche Semantik für checked exceptions gelten soll.
Eine Funktion in Java kann nur Checked Exceptions werfen die in der exception spezifikation stehen. das wird zur compiletime gecheckt.
in der theorie klingt das super, in der praxis eher nicht.
-
Das Problem welches sich bei Java gezeigt hat ist dass es ab und an mal vorkommt dass im Interface etwas vergessen wurde.
Wenn ich nun eine Funktion habe die laut Interface keine (checked) Exception werfen darf, und dann im nachhinein draufkomme dass eine konkrete Implementierung dieses Interface einfach nicht mit den aufgezwungenen Exception-Specs machen kann... doof.
Oder wenn ich die Implementierung dringend ändern will (weil sie z.B. viel zu langsam ist, oder Fehler enthält, oder was auch immer), dies aber nicht kann ohne in einer Funktion die ehemals als "ich werfe nix" gekennzeichnet war nun doch was zu werfen ... auch doof.
In dem Fall wirft man in Java dann einfach eine unchecked Exception ... was auch nicht Sinn der Sache ist.
Real sieht das dann so aus: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4615343
p.S.: da finden sich dann Kommentare wie
One can not change entries() to throw a ZipException -
it is too late.
One could parse entries in ZipFile constructor, and
throw a ZipException if the entry is invalidDanke, checked Exceptions

p.p.S.: in "eigenem" Code (auch wenn's ne kleine bis mittelgrosse Firma ist), sehe ich das Problem eher weniger. Einfach die Exception-Spec ändern, und so lange bei allen Projekten "compile drücken, Fehler durchgehen, Exception nachtragen oder fangen, compile drücken, ..." spielen bis es überall durchgezogen ist.
Im Framework Code, oder wenn's mal ne grössere Firma ist ... ist's halt etwas sehr doof.
-
Das hört man ja ziemlich oft "man kann nicht nachträglich eine Exception hinzufügen, dann compiliert der Code nicht mehr". Dieses Argument zehntausendmal zu bringen, macht es aber nicht richtiger und zeigt IMHO ganz genau auf, wie misverstanden checked Exceptions sind.
Wenn ich eine neue Exception werfe, dann breche ich Clientcode. Und zwar immer. Egal, ob sie checked ist oder nicht. Wenn sie nicht checked ist, führt das vielleicht nicht zu Compilerfehlern sondern zu Laufzeitfehlern, besser ist das aber keineswegs. Ich hatte vorher Code, der in allen möglichen Situationen robust war und es jetzt nicht mehr ist, möglicherweise sogar von mir unbemerkt. Da sind mir Compilerfehler lieber. Die Abwesenheit von Compilerfehlern bedeuted umgekehrt nicht, dass der Code noch funktioniert.
p.S.: da finden sich dann Kommentare wie Zitat:
One can not change entries() to throw a ZipException -
it is too late.
One could parse entries in ZipFile constructor, and
throw a ZipException if the entry is invalidDanke, checked Exceptions
Es ist nicht wegen checked Exceptions zu spät. Es ist zu spät, weil kein Clientcode mit dieser Exception rechnet.
Probleme mit checked Exceptions sehe ich eher im Aufwand während der Entwicklung. Wenn sich ständig was ändert, verliert irgendwann jeder im Team die Lust, die Exception-Spezifikationen überall anzupassen und wirft nur noch unchecked. Das ist verständlich und man bräuchte IMHO einen Weg, checked Exceptions zunächst einmal ignorieren zu können und vor dem Release dann zu aktivieren.
- Optimizer