Checked Exceptions
-
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ä?
-
@MBCS-CITP:
so in etwa?:void test() { try { int i = 5; try { int j = 6; try { printf( "5 + 6 = %i", i+j); } catch(const bad_alloc&) { printf( "kein Speicher für temporäres i+j"); } } catch(const bad_alloc&) { printf( "kein Speicher für j"); } } catch(const bad_alloc&) { printf( "kein Speicher für i"); } }Ich hoffe, das ist nicht dein Ernst
Und was bringt es Dir, das abzufangen? Wozu gibt es Objekte mit automatic storage und was bringt RIAA? Warum wurden Exceptions eingeführt, wenn man sie sofort wieder catchen will? Und was sind die Nachteile von Returncodes?Bevor jemand meckert: Jede Optimierung und Sinnlosigkeit sei vernachlässigt

-
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.
Das ist eigentlich kaum Arbeit. Man kann das ja schon mit einem try..catch in der main erreichen. Oder an einer anderen Stelle, an der man sinnvoll auf diese Exception reagieren kann.
-
Du hast dann zwar ein Mssg., dass z. B. ein Constructor eine Exception wirft, aber weisst immer noch nicht in welchen Zusammenhang. Wenn Du von einer Klasse viele Instanzen an unterschiedlichen Orten creierst, so hilft das wenig bei der Fehlersuche.
-
MBCS-CITP schrieb:
Du hast dann zwar ein Mssg., dass z. B. ein Constructor eine Exception wirft, aber weisst immer noch nicht in welchen Zusammenhang. Wenn Du von einer Klasse viele Instanzen an unterschiedlichen Orten creierst, so hilft das wenig bei der Fehlersuche.
hast du keinen debugger?
-
volkard schrieb:
hast du keinen debugger?
Das Problem ist bei nicht zu allocierenden Speicher, dass dies oft bei der Debugg-Version nicht auftritt, sehr wohl aber bei der optimierten Version (hatte auch schon entsprechende Probleme mit dem Stack). Diese enthaelt aber keine Debug-Informationen mehr. D. h. selbst das prozierte Schreiben eines Core-Files nutzt nicht mehr viel.
-
Was interessiert es denn, wo man keinen Speicher mehr bekommen hat? Wenn man eh keinen Speicher mehr bekommt, kann man doch sowieso nur noch die weiße Fahne schwenken. Und zwar am besten an irgendeiner zentralen Stelle. Übrigens mit der Hoffnung, dass durch automatisches Abräumen bis dahin schon wieder n bissl Speicher frei geworden ist.
-
7H3 N4C3R schrieb:
Was interessiert es denn, wo man keinen Speicher mehr bekommen hat? Wenn man eh keinen Speicher mehr bekommt, kann man doch sowieso nur noch die weiße Fahne schwenken. Und zwar am besten an irgendeiner zentralen Stelle.
Dann beginnt erst die Arbeit. Man muss dann einen Heapwalk machen, um zu sehen, wie der Speicher eigentlich aussieht. Wenn es z. B. an einer zu starken Fragnmentierung lag (sollte kein Problem mehr sein, die Prozessoren sind schon recht clever), muss man groesse Blocke Heap mit einem Schwung allocieren oder, so moeglich, zum Beginn des Programmes den max. benoetigen Haep berechnenen und dann allocieren. In Falle von Stack-Overflow muss man sehen, wie man Variablen in den Stack schiebt und z. B. Referenze-Uebergaben durch Pointer ersetzen, Klassen nicht als locale Variable in den Stack schreiben, sondern innerhalb des Blockes eine neue Instanz mittels des new-Operators in den Haep schreiben und dann wieder loeschen. Man muss sich dann auch anschauen, wie man notwendige Recursionen stack-optimiert.
-
Und dann ist der Heap voll... und dann?
Schreibst Du dir einen eigenen Allocator, dass Du weißt, wie dein Speicher aussieht?
Ich glaube, wenn man alle Ressourcen verbrezelt hat, sollte man sich eher mal ein paar Gedanken über seine Algorithmen machen.
-
7H3 N4C3R schrieb:
Ich glaube, wenn man alle Ressourcen verbrezelt hat, sollte man sich eher mal ein paar Gedanken über seine Algorithmen machen.
Nicht unbedingt - es kann z. B. eine Amok laufende Recursion sein, bei der ein Typo in der Abbruchbedingung diese sehr viel mehr Speicher allocieren laesst, als notwendig. Es kann auch sein, dass Datentypen zu aufgeblaeht sind (Daten doppelt und dreifach, statt mit referenzen oder Zeigern zu den Daten zu arbeiten). Die Moeglichkeiten sind viele und dort kann eigentlich nur eine Analyse des Heaps weiterhelfen.
-
Sowas sind doch aber Entwicklungsfehler/-probleme, und nichts was mal der Kunde zu spüren bekommt. Sowas bekommst du mit Debugger und ein paar nützlichen Tools wesentlich besser hin. Und so einen Entwicklungsaufwand kann man wohl nur schwer rechtfertigen. Außerdem eröffnest Du dir so Optimierungspotenzial für eine Version 2.0
