Checked Exceptions
-
Michael E. schrieb:
Hilft std::uncaught_exception nur bei von std::exception abgeleiteten Objekten?
Ich bekomms net hin dass std::uncaught_exception true gibt... Das hab ich versucht:
#include <iostream> #include <exception> using namespace std; struct Error { Error() { cout << "Error::Error()" << endl; if(uncaught_exception()) { cout << "Uncaught Exception in Error::Error()." << endl; } } ~Error() { cout << "Error::~Error()" << endl; } }; struct Foo { Foo() { cout << "Foo::Foo()" << endl; } ~Foo() { cout << "Foo::~Foo()" << endl; if(uncaught_exception()) { cout << "Uncaught Exception in Foo::~Foo()." << endl; } } template<class T> void Bar(T err) { cout << "Foo::Bar()" << endl; throw err; } }; int main() { try { Foo foo; foo.Bar(Error()); // foo.Bar(runtime_error("x"));, } catch(...) { cout << "Exception handling in int main()" << endl; } cout << "End"; cin.get(); }Ausgabe (bei std-exception das selbe nur ohne Error::x meldungen)
Foo::Foo() Error::Error() Foo::Bar() Error::~Error() Error::~Error() Foo::~Foo() Exception handling in int main() Error::~Error() EndIrgendwie hab ich das net erwartet... Ich dachte mehr an:
Foo::Foo() Foo::Bar() Error::Error() Uncaught Exception in Error::Error(). Foo::~Foo() Exception handling in int main() Error::~Error() Endhabs unter BCD6 getestet weil ich nix anderes da hab.
may be im just stupid...
/edit: der gcc sagt wieder was anderes TT
-
groovemaster schrieb:
Der einzige Nachteil an dieser ganzen Geschichte ist, dass du prkatisch in jeder Funktion am Beginn die Instanzierung vornehmen musst.
Ich sage dazu nur: Aspekt Orientierte Programmierung hilft da weiter!
-
FireFlow schrieb:
foo.Bar(Error()); // foo.Bar(runtime_error("x"));,Das lokale Objekt vom Typ Error wird schon vor Ausführung des Rumpfes von Foo::Bar<>() konstruiert. Deshalb wurde noch gar keine Exception geworfen.
-
Michael E. schrieb:
FireFlow schrieb:
foo.Bar(Error()); // foo.Bar(runtime_error("x"));,Das lokale Objekt vom Typ Error wird schon vor Ausführung des Rumpfes von Foo::Bar<>() konstruiert. Deshalb wurde noch gar keine Exception geworfen.
Ok das hab ich nun kapiert... Ich hab auch verstanden dass weil ich kein Copy C'tor hab ich mehr Dekonstruktoraufrufe hab als Konstruktoraufrufe (hoffe ich zumindest dass es daran liegt, muss nochmal testen). Nun ich habs nochmal im GCC und in VC8 getestet und da bekomm ich jeweils die Meldung `Uncaught Exception in Foo::~Foo().` - Im Borland aber nicht, ist der BCB in der Hinsicht mal wieder nicht Standardkonform oder ist das Verhalten undefined?
-
Will man unter Linux einen Backtrace haben nimmt man die Funktionen aus
#include <execinfo.h>
http://www.gnu.org/software/libc/manual/html_node/Backtraces.html
In unserem Projekt wird das so gemacht, dass wir nur eigene Exceptions werfen. Diese sammeln im Konstruktor die Funktionszeiger auf, die backtrace() liefert.
Wird die Exception dann gefangen, kann man sich den Backtrace mit Namen von backtrace_symbols() ausgeben lassen.
-
Funzt das auch im Release-Modus ohne Debug-Infos?
-
Fireflow:
ISO/IEC 14882:1998 schrieb:
18.6.4 uncaught_exception
bool uncaught_exception();
Returns: "true" after completing evaluation of a throw-expressionuntil either completing initialization of the exception-declaration in the matching handler or entering "unexpected()" due to the throw; or after entering "terminate()" for any reason other than explicit call to "terminate()". [Note: This includes stack unwinding (15.2). --end note]
-
Kann das also nur in Dekonstruktoren true ergeben? Ich meine danach wird der Block ja sofort verlassen und in den catch-Block gesprungen.
-
backtracing schrieb:
Funzt das auch im Release-Modus ohne Debug-Infos?
Ja, kann dir aber nur das sagen, was auch vorhanden ist. Das ist dann oft recht wenig.
-
FireFlow schrieb:
Kann das also nur in Dekonstruktoren true ergeben?
In deinem Fall ja.
-
Michael E. schrieb:
FireFlow schrieb:
Kann das also nur in Dekonstruktoren true ergeben?
In deinem Fall ja.
Hast du villeicht mal nen Beispiel wo es nicht im Dekonstruktor ist und trotzdem true ergibt? Mir fällt nix ein...
-
Sollte man eh nie benutzen.
Hier hast Du interessante Lektüre dazu:
http://www.gotw.ca/gotw/047.htmZitat von Sutter:
Is there any other good use for uncaught_exception? Discuss and draw conclusions.Unfortunately, I do not know of any good and safe use for std::uncaught_exception. My advice: Don't use it.
-
Hmm, gut zu wissen. Habs aber auch noch nie benutzt :p
-
FireFlow: Wenn du im Destruktor eine Funktion aufrufst, kann es dort auftreten:
#include <iostream> #include <exception> using namespace std; class Foo { public: void finalize() { if(uncaught_exception()) cout << "uncaught exception"; } ~Foo() { finalize(); // do other things } }; int main() { try { Foo foo; throw 1; } catch(...) { } }Oder wenn du im Destruktor ein Objekt erstellst, kann es im Konstruktor auftreten:
#include <iostream> #include <exception> using namespace std; class Bar { public: Bar() { if(uncaught_exception()) cout << "uncaught exception"; } }; class Foo { public: ~Foo() { Bar bar; // do other things } }; int main() { try { Foo foo; throw 1; } catch(...) { } }Aber grundsätzlich läufts über den Destruktor.
-
Hallo @all,
sorry, wenn ich diesen Beitrag jetzt wiederrechtlich okkupiere, aber es passt einfach zu gut zum Thema.
Ich habe mal ein bisschen mit exception specs rumgespielt. Ich hätte eigentlich gedacht, das der Compiler bei folgendem Code meckert:void some_func() throw( exception ) { throw exception ( "myExcept" ); } void MyAlloc(void) throw() { some_func(); }Ich hätte erwartet, das es zumindest ein warning giebt, da some_func ja wirft und das die spec von MyAlloc als Nothrow verletzt.
Nach diesem Artikel : http://www.gotw.ca/publications/mill22.htm :Never write an exception specification.
Eigentlich schade, weil ich es schon ganz schön finden würde, das vom Compiler zumindest teilweise checken zu lassen, ob ein exception - system konsistent ist. Außerdem müßte ich ja auch immer auf unexpected testen, wenn ich es dennoch benutze, weil ja alle compiler (zumindest VC, und g++) das komplett ignorieren.
-
TheBigW schrieb:
Eigentlich schade, weil ich es schon ganz schön finden würde, das vom Compiler zumindest teilweise checken zu lassen, ob ein exception - system konsistent ist.
Das geht aus 2 Gründen nicht. Erstens gibt es eine Menge Legacy-Code, der keine Exception-Spezifikationen enthält, obwohl er Exceptions wirft. Und zweitens kannst du bei Templates nicht wissen, welche Exceptions fliegen, da das Template-Argument beliebige Exceptions werfen kann.
-
Das ist mir schon klar, aber das wie bei meinem Beispiel eindeutige Verletzungen nicht angezeigt werden ist schon schade.
Meine eigentliche Frage hab ich dann wohl etwas unsauber formuliert : inwieweit ist dann die Verwendung von exception specifications sinnvoll : sie werden selbst in selbst geschriebenm Code nicht ausgewertet (Ich unterstelle mal, das man es konsequent umgesetzt hat) und ich muß mich mit obendrein damit herumschlagen, den Fall zu behandeln, das meine Spezifikation verletzt wird und bad_exception behandeln.
Es wäre also wirklich sinnvoller die spec wegzulassen und in die Dokumentation zu verschieben.Erstens gibt es eine Menge Legacy-Code, der keine Exception-Spezifikationen enthält, obwohl er Exceptions wirft
Na gut, der Fall wäre, das dieser code alles werfen kann. Das ist doch aber kein Begründung, warum man es im eigenen Code nicht wirklich verwenden kann.
Und zweitens kannst du bei Templates nicht wissen, welche Exceptions fliegen, da das Template-Argument beliebige Exceptions werfen kann
richtig, aber wenn ich eine template funktion habe, die als Nothrow (throw()) deklariert ist, dann giebt es halt einen Fehler wenn ein Template Argument verwendet wird, was eine andere spec hat.
-
Man basiert aber oft auf horrend vielen Funktionen, von denen es schlichtweg unmöglich ist festzustellen, welche Exceptions sie werfen. Wieviele Stellen gibt es z.B., die ein bad_alloc werfen könnten...
Man sollte lieber (hohe - falls sinnvoll) Exceptionsicherheit anstreben anstatt sich sorgen zu machen, was so alles geworfen wird. So ziemlich alle STL Container machen z.B. sich absolut keine Platte drum, ob nun irgendwo eine Exception geworfen wird. Sie bleiben aber trotzdem immer in einem konsistenten Zustand.
-
7H3 N4C3R schrieb:
Man basiert aber oft auf horrend vielen Funktionen, von denen es schlichtweg unmöglich ist festzustellen, welche Exceptions sie werfen. Wieviele Stellen gibt es z.B., die ein bad_alloc werfen könnten...
Wobei wir damit dem Grund haben, jede Allocierung von Speicher (schliesslich macht dies jeder new-Operator) abzufangen als try-catch. Das ist zwar Arbeit, aber es hilft.
-
MBCS-CITP schrieb:
Wobei wir damit dem Grund haben, jede Allocierung von Speicher (schliesslich macht dies jeder new-Operator) abzufangen als try-catch. Das ist zwar Arbeit, aber es hilft.
hä?