Nullen setzten
-
Noch eine Frage, Shade:
Warum hast du hier exp nochmal geklammert?
if(!(exp))
-
Shade Of Mine schrieb:
ein assert() in einem Destruktor?
Wieso sollte so etwas vorkommen, bzw. inwiefern sollte dies schlechter sein als ein normales assert()?Zum Beispiel habe ich eine Grafikengine und viele Texturen. Die Texturen müssen auf derselben Grafikengine erstellt und dann auch gelöscht werden. Eine Textur länger zu verwenden, als die Grafikengine existiert, ist illegal. Also überprüft der Dtor der Grafikengine, ob alle Texturen freigegeben sind - sind sie es nicht, hat entweder der Benutzer der Klassen (=ich) Mist bei der Resourcenfreigabe gemacht oder im Grafiksystem selbst ist ein Fehler. (Das ganze Texturmanagement ist intern auch nicht gerade einfach.) Viel mehr als terminate() bleibt einem da nicht mehr übrig: Wenn die Invarianten meiner Klassen nicht eingehalten sind, können sie eventuell nicht einmal freigegeben werden.
Das Problem mit Dtoren ist dann noch, dass werfende Dtoren allgemein für schlechten Stil gehalten und deshalb in den meisten Überlegungen ignoriert werden. Viel Code (auch der von wiederum anderen Dtoren) verlässt sich einfach darauf, dass Dtoren nie werfen. Die Möglichkeiten für Undefined Behaviour breiten sich damit immer weiter aus.
Da ist mir der der Standard-assert-Dialog lieber, der gleich Debugging anbietet, auch wenn man es ohne Debugger gestartet hat. Im schlimmsten Fall kosten mich die Leaks einen Reboot pro entdecktem Logikfehler, und die meisten Resourcen, die ich verwalte, sind nicht einmal so kritisch. Der Aspekt sieht aber natürlich bei jedem anders aus.
-
marco9 schrieb:
Was passiert denn, wenn eine Exception im Destruktor ausgelöst wird? Ist das dann undefiniertes Verhalten?
nein, aber wenn bereits eine exception im werfen ist, kann es probleme geben:
class Gefaehrlich { public: ~Gefaehrlich () { throw "blub"; } }; int main () { try { Gefaehrlich g; throw "Hello World!"; } catch (const char *c) { cout << c << '\n'; } }
kannst du mal ausprobieren. 2 exceptions gleichzeitig lassen std::terminate seine grausamen terminierungsanweisungen ausführen
absichern dagegen geht zb mitclass GefahrGebannt { public: ~GefahrGebannt () { if (!uncaught_exception()) throw "Neue Exception!"; } };
aber das ist ebenso für manche programmierer, die davon ausgehen, das destruktoren niemals ausnahmen werfen, gefährlich.
also lieber dtors nicht ausnahmen werfen lassen.zum thema resourcenfreigeben: man kann doch nicht im terminate_handler absicherungen unterbringen, oder? sinnvoll? lieber keine ausnahmen in dtoren?
-
@operator void:
Und inwiefern ist da das terminate() besser als mein Assert() ?Bitte vergiss nicht, dass man bei meinem Assert() dann den Fehler abfangen kann und eine schöne Fehlermeldung ausgeben (und danach erst beenden).
Wie davie ja schon erklärt hat kann es zu Problemen kommen wenn eine Exception einen Dtor verlässt. Aber bei einem terminate() wird garnichts zerstört.
Ich bevorzuge da lieber die Variante mit den wenigeren Ressourcenlöchern. Wenn jemand eine bessere Variante kennt -> nur her damit.
@marco9:
Der Operator ! hat eine sehr starke Bindung
Damit es da nicht zu Problemen kommt habe ich sicherheitshalber geklammert.@davie:
uncaught_exception() ist in der Theorie natürlich recht praktisch, aber in der Praktit liefert es bei fast allen Compilern immer false
-
hmm ich hab davon gehört und es mit dem gcc ausprobiert. da funktioniert es
aber ob es das wirklich wert ist?
-
Shade Of Mine schrieb:
@operator void:
Und inwiefern ist da das terminate() besser als mein Assert() ?Mir sind potenzielle Resourcenleaks lieber als ein Haufen undefiniertes (und dabei auch unüberschaubares) Verhalten. Und wie gesagt, assert() verwende ich, um grundlegende Invarianten sicherzustellen und dafür ist es imho auch sehr brauchbar. Wenn ein assert fehlschlägt, ist die Möglichkeit des sauberen Aufräumens nicht gegeben. An der Stelle, wo in meinem Beispiel die Grafikengine merkt, dass die Texturen nicht ordnungsgemäß freigegeben wurden, kann sie einfach nicht viel Sinnvolleres mehr tun als den Fehler so klar wie möglich auszugeben und auf die Behebung des Fehlers durch mich zu warten. (Natürlich könnte man da noch einen komplizierten Mechanismus drumrum bauen, aber man kann die Texturen auch einfach richtig freigeben
)
-
operator void schrieb:
ein Haufen undefiniertes (und dabei auch unüberschaubares) Verhalten.
wenn 2 exceptions geworfen werden, ist das aber nicht undefiniert. was meinst du?
-
Hallo,
nur noch mal zur Erinnerung: uncaught_exception sagt nur, ob eine Exception gerade *aktiv* ist. Es sagt nicht, ob es sicher ist, eine Exception zu werfen.Ich halte es bei diesem Thema mit Herb Sutter: http://www.gotw.ca/gotw/047.htm
Die Aufregung um die Resourcen-Löcher kann ich nicht teilen. Wenn in meinem Programm eine Assertion verletzt wird, dann sind Resourcenlöcher ein kleineres Problem. Eine Assertion ist ja eben *keine* Ausnahme (auch wenn man sie gut über den Ausnahmemechanismus implementieren kann).
Es ist nichts auf das ich vorbereitet bin und auf das ich geregelt reagieren kann/will.
Eine fehlgeschlagene Assertion ist ein Bug. Meldung/Aus/Zurück an den Schreibtisch. Häufig habe ich in diesem Moment einen Programmzustand der nicht definiert ist. D.h. aber auch, dass ich nicht alles ordentlich abbauen kann.
Natürlich sollte man meiner Meinung nach versuchen, soviel wie möglich so sauber wie möglich zu beenden. Aber das wichtigste ist die fehlgeschlagene Assertion, nicht deren Behandlung.Ich lasse meine Assertions standardmäßig natürlich auch in der Release-Version an. Schließlich verschwinden Bugs nicht durch das Ausschalten des Debug-Flags
-
davie schrieb:
wenn 2 exceptions geworfen werden, ist das aber nicht undefiniert. was meinst du?
Nicht automatisch, aber viel Code verlässt sich einfach darauf, dass ein Destruktor keine Exception wirft - ich glaube, das fängt bei den STL-Containern an (finde die entsprechende Liste aber gerade nicht in der MSDN). Wenn man sich daran nicht hält, betritt man offiziell schon das Land des undefinierten Verhaltens.
-
Wenn man sich daran nicht hält, betritt man offiziell schon das Land des undefinierten Verhaltens.
Nicht wirklich. Man betritt dann ein Land in dem alle Exception-Garantien *nicht* mehr gelten. Die STL-Container z.B. geben ihre Garantien nur unter bestimmten Voraussetzungen. Und eine davon ist, dass der Dtor der User-Klassen keine Exceptions schmeißt.
Oder kurz: Dtoren die schmeißen sind böse.
-
HumeSikkins schrieb:
Nicht wirklich. Man betritt dann ein Land in dem alle Exception-Garantien *nicht* mehr gelten. Die STL-Container z.B. geben ihre Garantien nur unter bestimmten Voraussetzungen. Und eine davon ist, dass der Dtor der User-Klassen keine Exceptions schmeißt.
Aber die Zerstörbarkeitsgarantie bleibt erhalten? Wenn nicht, ist das doch fast schon undefiniertes Verhalten... naja, lasse ich lieber die Finger von den Fachausdrücken und sage auch einfach "böse"
-
Aber die Zerstörbarkeitsgarantie bleibt erhalten?
Das ist die Basisgarantie. Der Zustand ist nicht notwendigerweise vorhersagbar, aber alle Objekte sind zerstörbar und es entstehen keine Leaks.
Dies kannst du *im Allgemeinen nicht* garantieren, wenn deine Dtoren schmeißen können. Also lautet die Antwort auf die Frage: nein.
-
Ahjo, danke
-
THX@PAD! Hat geklappt