Einwände gegen Ausnahmen

8

Einer meiner Freunde hat mich angesprochen. Ich steckte fest, weil ich nicht in der Lage bin, Ausnahmen zu benutzen. Denken Sie daran, dass wir beide in einer Arbeitsumgebung arbeiten, in der wir C ++ verwenden, aber die Fehlerbehandlung in C-Tradition durchführen. Sein Problem war in etwa so:

Funktion A ruft B auf, was wiederum C aufruft. Eine Ausnahme wird von C ausgelöst, und der catch-Block für diese Ausnahme befindet sich in A . Was passiert mit Ressourcen, die in B vor dem Aufruf von C erworben wurden? Wie säubern wir diese? Meine Antwort war Verwendung RAII. Aber selbst als ich es sagte, wusste ich, dass es nicht funktionieren würde. Wir haben riesige Codebasen, die im C-Modus geschrieben wurden. Nirgends im Code habe ich Autozeiger und so gesehen. Ressourcen sind nicht unbedingt in Klassen eingepackt. Selbst wenn sie es sind, bleiben die Destruktoren in den meisten Fällen für den Compiler übrig. Kurz gesagt, alles wird manuell erledigt.

Das eigentliche Problem ist, was zu tun ist, um den Übergang von der C-Fehlerbehandlung zu Ausnahmen mit dem Gewicht einer riesigen Codebasis zu machen? Das von meinem Freund gestellte Problem ist nur eine der möglichen Fragen, die aufgeworfen werden können, wenn Sie mit der C-Fehlerbehandlung vertraut sind und wissen möchten, wie die Migration von dort zu Ausnahmen erfolgen kann.

    
nakiya 11.02.2011, 09:09
quelle

7 Antworten

5

Es gibt eine Technik, die von Andrei Alexandrescu und Joshua Lehrer entwickelt wurde und Scope Guard genannt wird und eine Technik für Bereitstellen eines "Scope-Exit" -Codes, sobald Sie ein Objekt zuweisen und an diesem Punkt den Bereich dafür öffnen.

Die Programmiersprache D hat es eigentlich als Standard.

boost libraries hat eine Erweiterung namens Scope Exit . Wenn Ihr Code nicht ausnahmesicher ist, funktioniert die Funktion B nicht, sie wird nicht korrekt behandelt, wenn etwas ausgelöst wird.

Destruktoren werden beim Abwickeln des Call-Stacks nach einer Exception ausgeführt. Deshalb müssen Sie sicherstellen, dass sie selbst keine Ausnahmen auslösen.

    
CashCow 11.02.2011, 09:18
quelle
2
  

Das eigentliche Problem ist, was zu tun ist, um den Übergang von C-Fehlerbehandlung zu Ausnahmen mit dem Gewicht einer riesigen Codebasis zu machen?

Nein, das eigentliche Problem ist, dass Sie, da Sie in C ++ programmieren, längst damit fertig sein sollten. Selbst wenn Ihr eigener Code keine Exceptions auslöst, könnte ein Code in die Standardbibliothek und das Laufzeitsystem werfen ( new , dynamic_cast ) und natürlich alle Software von Drittanbietern, die Sie verwenden könnten, war gut.

Ich stimme zu, dass Scope Guard wahrscheinlich die beste Option ist, die Ausnahmesicherheit nachträglich hinzuzufügen. Täuschen Sie sich jedoch nicht, indem Sie denken, dass Sie das nicht tun müssen, solange Sie keine Ausnahmen selbst auslösen. Sie verwenden eine Sprache mit Ausnahmen . Beginnen Sie also so schnell wie möglich damit.

    
sbi 11.02.2011 10:11
quelle
1

Sie sollten trotzdem zu RAII migrieren, da Sie unter anderem keine Fehler machen können, wenn Sie den Kontrollfluss ändern. Sie müssen upgraden. Ausnahmen bedeuten, dass Sie keine Funktion, die eine Ausnahme enthalten kann, halb aufrüsten können.

    
Puppy 11.02.2011 09:20
quelle
1

C ++ Unterstützt finally nicht, um Last-Minute-Zeug am Ende des Blocks zu verwalten.

Wenn die Funktion C eine Ausnahme auslöst, wird sie von der Funktion zurückgegeben. Das bedeutet, dass alle lokalen Variablen zerstört werden.
Dann kehrt das Programm zu dem Code in B zurück, es wird nach einem catch-Block suchen, es wird auf non geachtet und zurück zu Funktion A. Wieder werden alle lokalen Variablen in B freigegeben.

Sie müssen sich daran erinnern, dass Sie in C ++ arbeiten. Sie müssen Ihre Objekte verwalten. Wenn Sie also Objekte haben, die sich in B (mit Zeigern oder was auch immer) frei bewegen, dann ist das ein schlechter Codeentwurf, und sie werden nicht veröffentlicht.

Wenn Sie in B wissen, dass in C eine Ausnahme vorhanden sein könnte, können Sie einfach einen Haken setzen und dann die gefangene Ausnahme zurückwerfen.

>

Der nächste Block, den du erreichen kannst, benutzt finally und benutzt ihn, um Speicher freizugeben ... aber er wird nur eingegeben, wenn es tatsächlich eine Ausnahme gab, also ist es nicht identisch mit catch(...)

%Vor%

Wenn Sie genau wie ein finally -Block arbeiten möchten, können Sie Folgendes tun:

%Vor%

Für alle, die ein Problem mit finally ... haben, ist es immer noch ein Befehl und dies ist ein perfektes Beispiel dafür, dass goto oder break oder eine Inline-Funktion continue ersetzen kann.

Etwas mehr über goto

    
Yochai Timmer 11.02.2011 09:23
quelle
0

Ihr Freund hat genau das Recht. Dies ist einer der Gründe, warum Google intern keine Ausnahmen verwendet. Siehe Ссылка (und öffne den kleinen Pfeil), um das Problem zu erklären.

    
btilly 11.02.2011 09:20
quelle
0

Ein Auszug von meiner verlassenen Homepage ...

  

Ohne im Detail alles zu wiederholen   Probleme, die der Ausnahme innewohnen   Handhabung (1) Ich möchte nur die   Hauptidee: Der komplexe Teil ist nicht   wo die Ausnahme generiert wird   (werfen) oder wo die Ausnahme ist   gehandhabt (fangen) aber in den Methoden von   alle Klassen, die die Ausnahme übergibt   fast asynchron während   der Stapelabwickelprozess.

     

Achten Sie auf Methoden   geschrieben werden ist relativ einfach zu vermeiden   Ressourcen verlieren im Falle von Ausnahmen   (Verwendung von auto_ptr und ähnlichen Klassen)   aber die Dinge sind viel komplexer als   man berücksichtigt den logischen Zustand   des Objekts oder anderer Objekte   vor dem Wurf manipuliert. In dem   strengste Bedeutung von Ausnahme-Safe   Eine Methode sollte entweder erfolgreich sein oder   ein No-Op sein: mit anderen Worten die   logischer Zustand des aufgerufenen Objekts   (und andere involvierte Objekte) sollten sein   das gleiche, wenn eine Ausnahme ausgelöst wird: nein   Unterschied sollte durch sichtbar sein   die öffentliche Schnittstelle aller Beteiligten   Klassen.

...

  

(1) Für eine ausführliche Beschreibung lesen Sie die   Artikel "Ausnahmebehandlung: Ein Falsch   Sinn für Sicherheit "von Tom Cargill   verfügbar online oder das Interessante   Sammlung von Problemen / Lösungen, die   Dieser Artikel wurde auf USENET generiert   verfügbar auf dem Buch "Außergewöhnlich   C ++ "von Herb Sutter   ISBN = 0-201-61562-2.

    
6502 11.02.2011 09:34
quelle
0

Sei froh, dass du Ausnahmen hast. Überlegen Sie, was mit den Fehlerrückgabecodes in Ihrem Beispiel passiert. Die Funktion C gibt einen Fehlercode zurück. B , naiv wie es ist, schluckt es. Anrufer A , der in der Lage wäre, damit umzugehen, wird nicht einmal über den Fehler informiert.

Am besten gehen Sie von C direkt nach C ++ 0x. Es bietet eine neue Funktion, Lambda's. Dies sind anonyme Funktionen, die in anderen Funktionen definiert sind. Sie können Ihren C-Cleanup-Code dort eingeben und ihn von einem "Scopeguard" -Objekt aufrufen lassen. Beispiel (Ich würde das Makro überspringen)

    
MSalters 11.02.2011 10:29
quelle

Tags und Links