Error handling: Exception vs. Error return value
-
cooky451 schrieb:
Der Punkt ist, dass der eigentliche Grund warum Exceptions geworfen werden immer weniger vor kommt, je größer und zuverlässiger das Programm wird.
Hä? Du programmiertst, daß weniger oft der SPeicher ausgeht, die Platte besser ist und der Benutzer die CD nicht rausnimmt?
cooky451 schrieb:
Man hat ein Mini-Programm geschrieben dass ein Fenster öffnet auf dem drei Buttons sind? Jetzt failt CreateWindow? Wunderbar, Exception + exit. Was soll man auch sonst machen.
Soweit ok.
cooky451 schrieb:
Wenn man jetzt aber ein Programm mit 3 Fenstern und 20 Sub-Fenstern hat bei dem alles asynchron läuft und irgendwo kann da jetzt ein Fenster nicht geöffnet werden (oder eine Verbindung nicht hergestellt werden, was auch immer), ist das wirklich ein Grund große Teile des Codes zu überspringen? Eher nicht, das Programm bei so etwas mal eben weit zurückfallen zu lassen wäre wohl schwachsinn, der ganze Rest funktioniert doch noch.
Sagt ja keiner, daß die Exception erst in der main gefangen wird.
cooky451 schrieb:
Ein großes Argument für Exceptions das ich auch immer wieder lese ist die größere Menge an Fehlerbeschreibung die man da rein bekommt.
Das teile ich nicht.
cooky451 schrieb:
Hey, wenn man das unbedingt braucht: Man muss Exceptions ja nicht werfen!
Siehe z.B. Alexandrescus Expected<T>, durchaus ein interessantes Konzept.
Mal schauen.
cooky451 schrieb:
Noch schöner wäre allerdings, wenn der Compiler erkennen könnte, dass keine Exception geworfen werden kann, wenn man selbst kontrolliert.
Die gehts jetzt aber hoffentlich nicht nur um Performance.
-
cooky451 schrieb:
Skym0sh0 schrieb:
Ok, cooky: Du sagst also, dass durch bessere Programmierung Exceptions unnötiger werden, weil sie einfach nicht gebraucht werden?
Nein. Ich sage dass die Fälle in denen Exceptions sinnvoll sind, einfach immer weniger werden je größer das Programm wird.
*meld* Das Muster kenne ich:
Du mit Deinen kleinen Programmen kannst ja schreiben, wie Du willst. Aber echte Entwickler, diue echt große Programme schreiben, verwenden natürlich UML. Wer das nicht tut, der ist ein kleiner Zwerg.Ebenso muß man UN benutzen, sobald das Programm mal mehr als 20 Mannjahre braucht. Wer UN nicht benutzt, der hat null Ahnung.
Nur mit Struktogrammen kann man einigermaßen fehlerfrei planen. Wobei fehlerfreie Programme gibt es eh nicht, das ist mathematisch bewiesen.
Da verweise ich dann aber auf Fachliteratur: http://de.wikipedia.org/wiki/Des_Kaisers_neue_Kleider
-
cooky451 schrieb:
Sockets. Ein Server der gerade mit 10k Clienten verbunden ist, will nicht wirklich viel mehr als einen log-Eintrag machen wenn er nicht noch einen Socket erstellen kann. Wenn ein send/recv fehl schlägt vielleicht noch nicht einmal das.
Jo, aber wenn der Socket nicht erstellt werden kann, dann hab ichj zwei Möglichkeiten: Untebleiben und noch ein paarmal probieren, oder hochgehen und oben einfach weitermachen, der nächste CLient wird schon wieder einen Socket anlegen können. Wie weit hoch gehen? Ist mir unten völlig egal!!! Das erledigen Exceptions auf feinste Weise.
-
cooky451 schrieb:
Ja, aber du willst nur ne Fehlermeldung anzeigen und nicht wirklich viel Code im gleichen oder höheren Scope überspringen.
Falsch!
Der Benutzer hat "Connect" gedrückt. Ich mache Sockets auf, lese Config-Files, dabei steig ich doch schon drei Funktionslevel runter oder mehr. Und dann klappt was nicht. Also mache ich kein normales Fenster auf, sondern zeige ihm einen Fehlerdialog. Und zwar, indem die Exception ungefähr in der Höhe gefangen wird, wo der Benutzer den "Connect"-Knopf gedrückt hat.
Und? Die anderen 49 Sitzungsfenster bleiben davon doch unberührt und laufen normal weiter. Ob der DIalog modal angezeigt werden soll oder nicht? Hast freie Auswahl.
-
Das heisst, so in etwa würde das aussehen, Pseudocodemäßig
vector<Hash> hashings; void calcHash(Path p) { File f; f.open(p); Hash h = calcHashImpl(f); hashings.push_back(h); } int main() { Path path = getPath(); Threads = createThreads(5); Queue q; Thread[0].run( traversePathAndPushBack(path, q) ); while ( !q.empty() ) { Thread t = getNextFreeThread(Threads); t.run( calcHash(q.next()) ); } return 0; }
Dann wäre das hier in etwa deine Version:
vector<Hash> hashings; void calcHash(Path p) { File f; f.open(p); Hash h = calcHashImpl(f); if ( !h.failed() ) hashings.push_back(h); } int main() { Path path = getPath(); Threads = createThreads(5); Queue q; Thread[0].run( traversePathAndPushBack(path, q) ); while ( !q.empty() ) { Thread t = getNextFreeThread(Threads); t.run( calcHash(q.next()) ); } return 0; }
Und das hier die Version mit Exceptions:
vector<Hash> hashings; void calcHash(Path p) { File f; f.open(p); try { Hash h = calcHashImpl(f); hashings.push_back(h); } catch ( ... ) { cerr << "geht nicht" << endl; } } int main() { Path path = getPath(); Threads = createThreads(5); Queue q; Thread[0].run( traversePathAndPushBack(path, q) ); while ( !q.empty() ) { Thread t = getNextFreeThread(Threads); t.run( calcHash(q.next()) ); } return 0; }
Huch, auf einmal mischen sich noch Menschen hier ein ?! Oo
Die Hälfte von volkards Posts verstehe ich wieder nicht
Und Sarkasmus/Ironie kommt im Interwebz meistens scheisse, weil mans nicht unbedingt versteht
-
Was dem Linuxer seine Distribution ist dem C++ler seine exception!
In meinem aktuellen Projekt, das nur so vor Benutzer-abhängigen Dingen (Nein, keine Pille-Palle-Stringfelder die man mal so fix auf validität prüft) strotzt, wüsste ich nicht, wie ich ohne exceptions Herr der Lage würde...
-
volkard schrieb:
cooky451 schrieb:
Skym0sh0 schrieb:
Ok, cooky: Du sagst also, dass durch bessere Programmierung Exceptions unnötiger werden, weil sie einfach nicht gebraucht werden?
Nein. Ich sage dass die Fälle in denen Exceptions sinnvoll sind, einfach immer weniger werden je größer das Programm wird.
*meld* Das Muster kenne ich:
Du mit Deinen kleinen Programmen kannst ja schreiben, wie Du willst. Aber echte Entwickler, diue echt große Programme schreiben, verwenden natürlich UML. Wer das nicht tut, der ist ein kleiner Zwerg.Ebenso muß man UN benutzen, sobald das Programm mal mehr als 20 Mannjahre braucht. Wer UN nicht benutzt, der hat null Ahnung.
Nur mit Struktogrammen kann man einigermaßen fehlerfrei planen. Wobei fehlerfreie Programme gibt es eh nicht, das ist mathematisch bewiesen.
Da verweise ich dann aber auf Fachliteratur: http://de.wikipedia.org/wiki/Des_Kaisers_neue_Kleider
Ok, willst du damit sagen, dass cooky nur die Augen vershcließt vor dem Offensichtlichen?
Nämlich, dass auf jedenfall irgendwo etwas schiefgehen kann und damit alles zerschiest?
-
Skym0sh0 schrieb:
volkard schrieb:
cooky451 schrieb:
Skym0sh0 schrieb:
Ok, cooky: Du sagst also, dass durch bessere Programmierung Exceptions unnötiger werden, weil sie einfach nicht gebraucht werden?
Nein. Ich sage dass die Fälle in denen Exceptions sinnvoll sind, einfach immer weniger werden je größer das Programm wird.
*meld* Das Muster kenne ich:
Du mit Deinen kleinen Programmen kannst ja schreiben, wie Du willst. Aber echte Entwickler, diue echt große Programme schreiben, verwenden natürlich UML. Wer das nicht tut, der ist ein kleiner Zwerg.Ebenso muß man UN benutzen, sobald das Programm mal mehr als 20 Mannjahre braucht. Wer UN nicht benutzt, der hat null Ahnung.
Nur mit Struktogrammen kann man einigermaßen fehlerfrei planen. Wobei fehlerfreie Programme gibt es eh nicht, das ist mathematisch bewiesen.
Da verweise ich dann aber auf Fachliteratur: http://de.wikipedia.org/wiki/Des_Kaisers_neue_Kleider
Ok, willst du damit sagen, dass cooky nur die Augen vershcließt vor dem Offensichtlichen?
Nämlich, dass auf jedenfall irgendwo etwas schiefgehen kann und damit alles zerschiest?Nein. Ich will nur hiermit das Programmgrößenargument entwerten und weg haben.
-
Ich wüsste gerne einmal die Argumentation, die zu der Aussage führte...
-
Wenn Fehler nicht Teil des normalen Programmablaufs sind, nehm ich immer Exceptions/Asserts.
Exceptions sind deutlich eleganter, sicherer, auf vielen Rechnern performanter als Fehlercodes oä. als Rückgabewert.
-
Ethon schrieb:
auf vielen Rechnern performanter als Fehlercodes oä. als Rückgabewert.
Woher nimmst du die Info? Und vor allem, warum ist das so?
Ich dachte immer, Exceptions sind lahme Krücken.
-
theliquidwave schrieb:
Ethon schrieb:
auf vielen Rechnern performanter als Fehlercodes oä. als Rückgabewert.
Woher nimmst du die Info? Und vor allem, warum ist das so?
Ich dachte immer, Exceptions sind lahme Krücken.Auf x64-CPUs lässt sich Exception-Handling komplett kostenlos implementieren, WENN die Exception nicht fliegt. Wenn sie fliegt ist es teurer.
Aber da Fehler generell Ausnahmen und nicht Regelfall sind, kann man davon ausgehen dass es performanter ist. (Hab ja gesagt dass ich Return-Werte nutzen würde, wenn Fehler zum normalen Programmablauf gehören)
-
Wenn Fehler zum normalen Programmablauf zählen, dann handelt es sich ja eigentlich nicht um Fehler, oder? Dann sind es vielleicht Ereignisse oder Zustände^^
Z.b. halte ich eine IncompetentUserException für fragwürdig, wobei eine CompetentUserException schon nachvollziehbar ist!
-
Hier ein etwas anderer Ansatz: http://isocpp.org/blog/2012/12/systematic-error-handling-in-c-andrei-alexandrescu . Exceptions werden mit dem Wert verknueft. Sowas Wie Maybe/Either in Haskell, wie boost.optional nur mit Exceptions. Exceptions werden geworfen, wenn das Ergebnis benutzt wird. Wenn keine Exception geworfen werden soll, dann kann vorher mittels valid das Ergebnis geprueft werden. Der zweite Teil beschaeftigt sich mit ScopeGuards und wie im Fehlerfall elegant aufgeraemt werden kann.
-
Ethon schrieb:
Auf x64-CPUs lässt sich Exception-Handling komplett kostenlos implementieren
Ist das auch bei 32bit Prozessen so, die auf einem x64_86 System laufen? (Windows 8 64bit zun Beispiel)
-
theliquidwave schrieb:
Ethon schrieb:
Auf x64-CPUs lässt sich Exception-Handling komplett kostenlos implementieren
Ist das auch bei 32bit Prozessen so, die auf einem x64_86 System laufen? (Windows 8 64bit zun Beispiel)
Nein, ein 32bit Prozess ist ein 32bit Prozess.
Aber es ist nicht so als würde Exception Handling so teuer sein.
Du kannst dir das hier mal den ersten von meinem Artikel hier durch lesen:
http://www.c-plusplus.net/forum/219865
-
cooky451 schrieb:
Siehe z.B. Alexandrescus Expected<T>, durchaus ein interessantes Konzept.
Ich bin gerade dabei mir seinen Vortrag über genau das anzusehen, aber ich habe ein Problem mit dem Verstehen des Konstruktors.
template <class T> class Expected { union { T ham; std::exception_ptr spam; }; bool gotHam; // ... Expected(const Expected& rhs) : gotHam(rhs.gotHam) { if (gotHam) new(&ham) T(rhs.ham); // ^~~~~~~~~~~~~~~~~~~~~ else new(&spam) std::exception_ptr(rhs.spam); // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // was bedeutet das? } // ... };
Ich weiß, dass man den new-operator mit mehreren Parametern überladen kann, allerdings finde ich keine Überladung mit bool, geschweige denn mit T
Ich habe das jetzt so verstanden, dass (if-block:) ham mit einer kopie von rhs.ham bzw. (else-Block:) spam mit einer kopie von rhs.spam initialisiert wird
-
Cyres schrieb:
Ich bin gerade dabei mir seinen Vortrag über genau das anzusehen, aber ich habe ein Problem mit dem Verstehen des Konstruktors.
Was soll das in diesem Thread?
Expected(const Expected& rhs) : gotHam(rhs.gotHam) { if (gotHam) new(&ham) T(rhs.ham); // ^~~~~~~~~~~~~~~~~~~~~ else new(&spam) std::exception_ptr(rhs.spam); // ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // was bedeutet das? }
Das ist ein inplace-new.
Die union initialisiert erst einmal gar kein Member. Sie weiss ja nicht, ob du ham oder spam möchtest.Wenn du einen Wert im Unionmember ham haben möchtest, musst du den Konstruktor für das Element händisch aufrufen. Die Syntax dazu lautet halt new(&ham). Siehe http://en.cppreference.com/w/cpp/language/union
-
hamspammer schrieb:
Das ist ein inplace-new.
Auch placement-new genannt.
-
hamspammer schrieb:
Was soll das in diesem Thread?
Hier wurden verschiedene Arten von Error-Handling erläutert, zu einem davon habe ich Fragen, weil ich etwas davon nicht verstehe, also frage ich hier nach.
hamspammer schrieb:
Das ist ein inplace-new.
cooky451 schrieb:
Auch placement-new genannt.
Danke für die Antworten, gerade mit dem Begriff "placement-new" konnte ich mehr anfangen