Fragen zu try..catch
-
Hallole.
Ich programmiere ISAPI DLLs mit C.
Ich habe immer wieder C++ Elemente mit eingebaut und auch schon einige klassen verwendet.
Da ich noch in Sachen C++ Anfänger bin, aber weiterkommen möchte, versuche imer immer wieder was neues. Heute ist try-catch dran.Eigentlich sollte das ganz einfach sein, habe aber trotzdem das Problem, daß meine mit Absicht produzierte Ausnahme nicht abgefangen wird.
Dabei versuche ich es mit einer einfachen Division durch 0.try { int divisor=0; int dividend=1; int quotient = dividend/divisor; // hier knallt es! } catch (...) { WriteClient(pECB2,"hier knallt es"); }Das WriteClient ist einfach die ISAPI Funktion die den Text an den Webbrowser sendet, ist hier aber unrelevant.
Wenn ich das mit dem VC++ debugge bricht er ab, mit der Meldung, daß eine division durch 0 vorliegt, lasse ich das Programm laufen, schmiert es ab.
Dabei sollte er doch in den "catch" Zweig gehen und die Meldung ausgeben oder was habe ich falsch verstanden???Danke Mondmann
-
Du musst erst noch eine Exception werfen, damit dein Code funktioniert. Weißt du, der / operator wirft halt keine exceptions

D.h. du musstif (divisor == 0) throw divisor;einbauen, bevor zu teilst.
MfG
GPC
-
Hmm... das ist ja blöde....
Dann kann ich also ohne den Code von Dir nicht verhindern, daß das Programm abstürzt?
Dann ist doch der ganze Sinn von try...catch dahin oder?
Dann brauche ich das gar nimmer.
Dann mache ich ne if(divisor==0){"Fehlermeldung"}; - Schleife und alles ist gut.
Für was brauche ich dann noch try-catch?Ich dachte damit kann ich komfortabel verhindern, daß mein Programm abstützt, denn ich habe das schon mit anderen Versuchen getestet zb:
_snprintf_s(buffer,1024,1024,"%s%s%s%s%s",header,top,menue,main, footer)In diesem Fall stürzt das Programm ebenfalls ab, da der Text der in den buffer buffer um ein vielfaches größer ist als 1024(ist ja nur zum Testen).
Also was ist dann der Sinn von try-catch?
Danke Mondmann
-
Hallo,
hier ein Artikel von Reyx zu dem Thema: http://www.c-plusplus.net/forum/viewtopic-var-t-is-139074-and-start-is-0.html
Der erklärt das ziemlich gut. Und ich muss nicht so viel schreiben

MfG
GPC
-
Dann mache ich ne if(divisor==0){"Fehlermeldung"}; - Schleife und alles ist gut.
Was sind den diese coolen if-schleifen? Werden sie im neuen C++ Standard aufgenommen?
-
Ok danke mal.
Dann geht das leider nicht so einfach wie ich mir das vorgestellt hatte.
Ich meinte so auf die schnelle verhindern zu können, daß mein Programm durch div. durch 0 abstürzt mit try-catch.
Geht natürlich so nicht.
Somit werde ich bei if..else bleiben,da für mich try-catch keine wirklichen Vorteile bringt.Ich hatte das o.g. Beispiel aus einen C++ Tutorial.(http://www.willemer.de/informatik/cpp/exceptions.htm)
indem es so aufgezeigt wird, ohne abfragen des divisors nach 0.Aber ich schätze mal ich habs einfach noch nicht verstanden...
Danke für die Hilfe, Mondmann
-
Du mußt im genannten Text einfach nur [1] beachten (Text ganz unten auf der Seite). Ich habe noch keinen Compiler gehabt, der Division durch 0 so abfangen könnte.
-
Ok alles klar.
Ein Vorteil der mir jetzt einfällt, wäre folgender.
Ich fange ja alle möglichen Fehler ab. Wenns einen Fehler gibt, schreibe ich diesen in eine error.log Datei und kehre mit 0 auf der Funktion zurück.
Ich könnte dann hingehen und die gesamte Funktion in ein try() packen und bei einem Fehler, dessen Fehlertext werfen lassen.zB. throw("Fehler beim reservieren von Speicher. Fehler:1001");
Mit catch fange ich das dann ab und rufe die Funktion, die das in die log schreibt nur ein eiziges mal ab und schreibe "return 0;" dann auch nur ein einziges mal.
Somit könnte der Code übersichtlicher werden.
Wäre das ein evtl. Anwendungsgebiet?
Mondmann
-
Mondmann schrieb:
oder was habe ich falsch verstanden???
Nunja, wie GPC schon sagte, du kannst Exception nur mit catch fangen, wenn ein throw erfolgte. Division durch 0 ist eine Hardwareexception, sowas lässt sich nur unportabel abfangen. Mit WinAPI sollte sowas zB möglich sein.
-
Mondmann schrieb:
Ok alles klar.
Ein Vorteil der mir jetzt einfällt, wäre folgender.
Ich fange ja alle möglichen Fehler ab. Wenns einen Fehler gibt, schreibe ich diesen in eine error.log Datei und kehre mit 0 auf der Funktion zurück.
Das ist genau die Methode, wie man es nicht machen sollte. Eine Funktion gibt eben keinen Fehlercode zurück, sondern wirft eine Exception. Dadurch muß der Aufrufer keinen Fehlercode abfragen sondern konzentriert sich auf seine eigentliche Aufgabe. Das schöne an Exceptions ist, daß diese über mehrere Funktionsaufrufe hinweg zurück geliefert werden. Dadurch kann ich an einer zentralen Stelle alle Fehler fangen, Nämlich da, wo ich sinnvollerweise darauf reagieren kann. Beispiel:
void aktion1() // kein Rückgabecode oder ähnliches! { // macht irgendwas if (irgendwas ist schief gelaufen) throw std::runtime_error("das hat nicht geklappt weil blah blah"); } void aktion2() { // eine Aktion, die aktion1 verwendet aktion1(); // keine Fehlerbehandlung hier, da ich mich hier auf meine Aufgabe, aktion1() auszulösen konzentiere } void aktion3() { // und noch eine schwachsinnige Funktion, die keine Fehlerbehandlung macht aktion1(); aktion2(); aktion2(); } int main() { try { aktion3(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; } }Obwohl in der 3. Aufrufhierarchie was schief läuft, muß nur das Hauptprogramm den Fehler behandeln. "aktion3" beispielsweise muß nicht erst abfragen, ob aktion1 erfolgreich war, und nur dann aktion2 aufrufen, sondern kann sich darauf verlassen, daß aktion1 erfolgreich war, wenn aktion2 aufgerufen wird.
Hätte ich das ohne Exceptions programmiert, würde aktion3 etwa so aussehen:
int aktion3() { int ret = aktion1(); if (ret != 0) return ret; ret = aktion2(); if (ret != 0) return ret; return aktion2(); }Ich bin der Meinung, daß hier wesentlich schwieriger zu erkennen ist, welche aktionen hier ausgeführt werden. Die anderen Funktionen sind natürlich entsprechend um Abfragen und returncodes zu erweitern.
Wenn ich in einer Funktion jetzt auch noch was zurück geben will, dann muß ich mir einen Wert überlegen, welcher den Fehlercode darstellt, oder aber eine Referenz auf eine Fehlercodevariable übergeben.
Nehmen wir an, wir schreiben eine Funktion div, die sicher darauf reagieren soll, wenn eine Division durch 0 erfolgt. Mit Exceptions sieht das so aus:
double div(double a, double b) { if (b == 0.0) throw NullDivision(); // ich nehme einfach mal an, wir hätten so eine Klasse definiert return a / b; } void f() // hier wird das verwendet { try { double d = div(5, 0); std::cout << "5/0=" << d << std::endl; } catch (const NullDivision&) { std::cerr << "oha - das geht nicht" << std::endl; } }Ohne Exceptions sähe das in etwa so aus:
double div(double a, double b, int& fehler) { if (b == 0.0) { fehler = 1; return 0.0; // eigentlich will ich das ja gar nicht :( } else { fehler = 0; return a / b; } } void f() { int fehler; double d = div(5, 0, fehler); if (fehler == 0) { std::cout << "5/0=" << d << std::endl; } else if (fehler == 1) { std::cerr << "oha - das geht nicht" << std::endl; } else { // jetzt weiß ich nicht mehr weiter } }
-
MSVC unterstützt z.B. asynchrone Exceptions in synchrone zu verwandeln, was wirklich SEHR COOL ist. Soll heissen: du installierst einen Handler, welcher aufgerufen wird wenn eine asynchrone Exception (division by zero, access violation, protection fault, ...) auftritt, und da drinn kannst du dann eine normale C++ Exception schmeissen die du auch ganz normal mit catch fangen kannst. Coole Sache.
-
Hallo tntnet.
Vielen Dank für Deine gute und sehr ausführliche Antwort die den Unterschiede sehr deutlich macht.
Ich habe bereits eine größere Funktion "umgewandelt" und werfe jetzt eben bei jedem Fehler etwas in der Gegend herum:-)
Und ich muss echt sagen es ist um ein vielfaches einfacher und übersichtlicher. Ich muss mich jetzt nicht mehr drum kümmern was die Funktion zurückgibt und dies entsprechend abfangen sondern fange den Fehler einfach ein und gebe ihn aus.
Dolle Sache.Vielen Dank für die "Erleuchtung".
Grüße Mondmann
-
Mondmann schrieb:
...
Und ich muss echt sagen es ist um ein vielfaches einfacher und übersichtlicher. ...Ja, exceptions gehören zu den Dingen, die ich am meisten vermisse, wenn ich in C (ohne "++") arbeiten muß (dann noch "overloading" und bisweilen templates ... die meisten anderen Sachen kann man noch einigermaßen emulieren).
Schon eine tolle Sache !
Gruß,
Simon2.
-
Mir sind Destruktoren wichtig. Das nimmt Dir das Resourcenhandling ab.
Tntnet
-
tntnet schrieb:
Mir sind Destruktoren wichtig. Das nimmt Dir das Resourcenhandling ab.
Tntnet
Stimmt !
... eigentlich fehlt alles, was C++ hat und C nicht
Und den Kontrollfluß bei exceptions kann man kaum sinnvoll nachbauen, während man bei einigem Anderen wenigsten noch "ähnliche Krücken" bauen kann.
Initialisierung/Abräumen wie per Ctor/Dtor geht noch halbwegs (finde ich) - ist zwar lästig (so wie die Funktionsbenennung ohne overloadiung und namespaces), aber wenigstens noch irgendwie abbildbar.Gruß,
Simon2.