Exception oder Rückgabewert?
-
Auf jeden Fall nur für "richtige" Fehler, bwz. für Sonderfälle wie Konstruktoren oder festgelegte Funktionsschnittstellen, überladene Operatoren oder redefinierte Funktionen...
-
Hallo
Rückgabewerte für Fehler, wenn der Fehler im weiteren Verlauf behoben werden kann.
Exceptions für Fehler, die zwar bestimmbar sind, aber auf jeden Fall zum geordneten Abbruch des Programms führen sollen
asserts für alle unerwarteten Fehler, nach denen es einfachen nicht weiter gehen kann
bis bald
akari
-
Exceptions sind aber nicht langsamer. Ganz im Gegenteil, bei Return-Werten machst du immer einer if-Abfrage, selbst wenn kein Fehler auftritt. Bei Exceptions kommst du in den catch-Block, nur wenn ein Fehler auftritt. Wenn kein Fehler auftritt, geht es ganz normal weiter im Programm. Das werfen einer Exception ist aber performancemäßig also völlig vertretbar.
Es gibt ja mehrere Exception-Kategorien. Z.B. Resourcen-Fehler (Drucker nicht ansprechbar) sollte man mit einer Exception weiter werfen. Benutzerfehler, z.B. eine falsch eingegebene PIN beim Geldautomaten, sollte man nicht als Exception werfen. Denn es ist ja kein unerwarteter Ausnahmefehler! Aber das ein Drucker auf einmal nicht ansprechbar ist, sollte man als "unerwartet" einordnen. OK, dann gibts halt noch Logicfehler, die man auch als Exceptions wirft. Laufzeitfehler werden eh autom. geworfen.
Exceptions haben außerdem noch den Vorteil, das man sie weiter reichen kann, wenn man selber nicht weiß, wie man auf einen Fehler regieren muß. Wie soll das bei einem Return-Wert vernünftig funktionieren? Da weiß doch am Ende niemand, was eigentlich falsch lief.
An Performance würde ich nicht meine Gedanken verschwenden, wenn es um Exceptions geht. Dafür relativiert sich nämlich alles wieder, was die Mächtigkeit von Exceptions angeht. Und Exceptions benötigen nur dann Performance, wenn sie wirklich geworfen werden. Wenn keine Fehler auftauchen, ist es sogar letztendlich schneller als eine if-Abfrage bei einem Return-Wert!
-
Artchi schrieb:
Wenn kein Fehler auftritt, geht es ganz normal weiter im Programm. Das werfen einer Exception ist aber performancemäßig also völlig vertretbar.
Ne, das werfen ist verdammt lahm - nur das nicht werfen ist verdammt schnell

Und in einem erfolgreichen Programmdurchlauf fliegt idR keine Exception - man ist also idR mit Exception sogar schneller als ohne
Denn es ist ja kein unerwarteter Ausnahmefehler!
Genau das bringt es auf den Punkt -> Exception sind Ausnahmen

OK, dann gibts halt noch Logicfehler, die man auch als Exceptions wirft.
Ich werfe idR nie einen std::logic_error - ich mache da eigentlich immer ein ASSERT()
Exceptions haben außerdem noch den Vorteil, das man sie weiter reichen kann, wenn man selber nicht weiß, wie man auf einen Fehler regieren muß.
Noch ein wichtiger Punkt

Exception erlauben das behandeln dort wo es Sinn macht und nicht dort wo der Fehler auftrat.Und Exceptions benötigen nur dann Performance, wenn sie wirklich geworfen werden.
Leider nicht - stack unwinding code ist nicht gratis
aber allemale billiger als 5 if (die ja alle bedingte sprünge beinhaltet -> goto ist böse :p)Wenn keine Fehler auftauchen, ist es sogar letztendlich schneller als eine if-Abfrage bei einem Return-Wert!
Full ACK
mal davon abgesehen, dass man return Werte gerne ignoriert
um eine Exception zu ignorieren muss man schon explizit catch(...){} schreiben. Und sowas fällt beim Code-Review dann auf, und man kann dem Programmierer dann eine auf die Finger geben 
-
Exceptions für Fehler, die zwar bestimmbar sind, aber auf jeden Fall zum geordneten Abbruch des Programms führen sollen
Nein. Woher nimmst du diese Weisheit bitte?
-
ich nehm exceptions am liebsten in solchen fällen
func() { //funcinit //mach was if ( fehler ) { //funcdeinit //return } //mach was if ( fehler ) { //funcdeinit //return } //mach was if ( fehler ) { //funcdeinit //return } //funcdeinit //return }func() { //funcinit try() { //mach was if ( fehler ) throw; //mach was if ( fehler ) throw; //mach was if ( fehler ) throw; } catch() { } //funcdeinit //return }gutes beispiel is wenn man z.b. ne datei aufmacht oder speicher allokiert
-
Sovok schrieb:
gutes beispiel is wenn man z.b. ne datei aufmacht oder speicher allokiert
Bitte sag, dass das nicht dein ernst ist.
da kann man ja gleich nur die return werte auslesen...
-
ich benutz es in dem fall nich um returnwerte nicht auslesen zu müssen, sondern um zeilen zu sparn
die einzige alternative die mir in dem fall einfällt is goto aber des benutz ich aus prinzip ned
-
.
Noch ein wichtiger Punkt
Exception erlauben das behandeln dort wo es Sinn macht und nicht dort wo der Fehler auftrat.das ist einerseits richtig, aber in 80% der fälle können fehler vor ort gelöst werden,und da hab ich persönlich doch eher ein if, in dem ich dann selber ne exception schmeissen kann, wenns wirklich nicht mehr an der stelle weitergehen kann. das problem an ner exception ist ja, dass man nicht mehr zurück in den code springen kann, wenn der fehler gelöst wurde, das macht diese ausnahmebehandlung nochmal teurer.
-
Hallo
Exceptions für Fehler, die zwar bestimmbar sind, aber auf jeden Fall zum geordneten Abbruch des Programms führen sollen
Nein. Woher nimmst du diese Weisheit bitte?
zum Beispiel wenn eine externe Datei, ein Registry-Schlüssel oder ein Server nicht erreichbar ist. Dann kann ich eine auch für den User sinnvolle Fehlermeldung ausgeben und das Programm auf jeden Fall beenden (wenn übergreifende try-Behandlung gibt)
Mit nicht bestimmbar meine ich, wenn eine Funktion mit
int foo(TClass *Class)mit Class == NULL aufgerufen wird, obwohl ein solcher Wert gar nicht verarbeitet werden kann.
bis bald
akari
-
Dafür nimmt man dann assert.
-
akari schrieb:
Hallo
Mit nicht bestimmbar meine ich, wenn eine Funktion mit
int foo(TClass *Class)mit Class == NULL aufgerufen wird, obwohl ein solcher Wert gar nicht verarbeitet werden kann.
bis bald
akaridas is meiner meinung nach der job von nem assert weil der input vom programmierer kommt und der programmierer sicherzustellen hat, dass er keine null pointer übergibt
int foo(TClass *Class) { assert ( Class != NULL ); }in der theorie könnte sich der übergabewert im debug und release modus unterscheiden falls dem system der speicher ausgeht
in der praxis gibts keinen unterschied wenns keine speicherintensive anwendung is
-
Shade Of Mine schrieb:
Sovok schrieb:
gutes beispiel is wenn man z.b. ne datei aufmacht oder speicher allokiert
Bitte sag, dass das nicht dein ernst ist.
da kann man ja gleich nur die return werte auslesen...wieso sollte man das nicht so machen? das problem ist ja, das alle standart-libs statt exception return wert liefern. ( auser der STL vieleicht )
ich benutzt exceptions häufig um das HRESULT aus directx auszuwerten. eine einzige exception-klasse die zu dem HRESULT einen info-text ausgibt. und in der winmain steht dann ein try catch mit fehlerdialog im catch block.
-
Hallo
Dafür nimmt man dann assert.
Exakt. Das habe ich auch in meinem ersten Post so dargestellt, habe es nur in der Erläuterung vergessen zu erwähnen.
bis bald
akari
-
DEvent schrieb:
wieso sollte man das nicht so machen? das problem ist ja, das alle stan****-libs statt exception return wert liefern. ( auser der STL vieleicht )
bei den IOStreams kann man exceptions einschalten und C Libraries wrappt man.
Und die anderen C++ Standard Funktionen können kaum fehlschlagen...wenn man
if(foo()) throw;
if(foo2()) throw;
schreibt, dann kann man sich exceptions ja gleich sparen - sie bringen hier nur verdammt wenig.ein
foo();
foo2();
ist hier viel schöner und eleganter (zudem kann man auch noch bessere exception werfen, weil man GetLastError()/errno oder sonstwas auswerten kann...
-
Merkregel: Fasse nie eine C-API roh an.
Wrap it up! 
-
Sovok schrieb:
ich benutz es in dem fall nich um returnwerte nicht auslesen zu müssen, sondern um zeilen zu sparn
die einzige alternative die mir in dem fall einfällt is goto aber des benutz ich aus prinzip ned
Ja ganz toll: Exceptions als Ersatz für das (teilweise zu Recht) verpönte goto zu benutzen...

-
Prüft ihr pointer generell mit Assert? Ich prüfe diese immer, wenn sie NULL sein können mit nem einfachen if (!p) /*mach irgendwas*/ und Asserts verwende ich nur zum prüfen von Arraygrenzen usw. oder wenn nen Zeiger wirklich niemals NULL sein kann.
Exceptions verwende ich dann wenn es Sinn macht z.B. wenn der Rückgabewert kein Fehlercode ist sondern ein Wert, oder wenn es wirklich eine Ausnahme ist, z.B. wenn die Rechte für eine Operation fehlen.
-
MaSTaH schrieb:
Sovok schrieb:
ich benutz es in dem fall nich um returnwerte nicht auslesen zu müssen, sondern um zeilen zu sparn
die einzige alternative die mir in dem fall einfällt is goto aber des benutz ich aus prinzip ned
Ja ganz toll: Exceptions als Ersatz für das (teilweise zu Recht) verpönte goto zu benutzen...

ne der wesentliche unterschied is, dass man per goto überall hinspringen kann wohingegen die exception zum ende des try blocks springt
find ich wesentlich definierteraber gehen wir mal zum spass von ner speicherintensiven anwendung aus bei der keine exceptions benutzt werden dürfen
char* p1=NULL,p2=NULL,p3=NULL; //mach was p1 = new char[/*variabel*/]; if ( p1 == NULL ) //return //mach was p2 = new char[/*variabel*/]; if ( p1 == NULL ) //return //mach was p3 = new char[/*variabel*/]; if ( p1 == NULL ) //returnwie würdest du hier am besten sicherstellen, dass aufgeräumt wird und gleichzeitig redundanten code vermeiden?
-
Indem ich SmartPointer verwende
:p 
mfg JJ