Wie vermeidet man es, std :: string in die Exception-Klasse zu setzen?

8

Hier ist meine Ausnahmeklasse:

%Vor%

Die Boost-Ausnahmerichtlinien empfehlen, keine Objekte zu platzieren, die Speicher als Mitglieder meiner Ausnahmeklasse zuweisen. In diesem Fall verletzt die Verwendung von std::string dies. Ich respektiere die Regel dafür, aber ich kann mir keinen Weg vorstellen, den what() override zu implementieren, ohne std :: string zu verwenden, um den Speicher zu verwalten (im Gegensatz zu dem Anrufer, ihn für mich zu verwalten).

Ich könnte einen Puffer fester Größe als Mitglied verwenden und C-Bibliotheksfunktionen (wie snprintf() ) verwenden, um die Aufgabe zu erledigen, aber das ist nicht sehr idiomatisch für C ++ und daher keine ideale Lösung.

Ist dies eine geeignete Implementierung einer Ausnahmeklasse? Wenn nicht, welche Verbesserungen können gemacht werden?

    
void.pointer 22.02.2012, 22:08
quelle

3 Antworten

6

Für das, was es wert ist, nehmen alle in <stdexcept> definierten Ausnahmetypen std::string als Argumente an. Dies könnte von den Bibliotheksdesignern so interpretiert werden, dass es "in Ordnung" ist. Ich denke, das Hauptargument dagegen ist, dass Sie, wenn Sie sich in einer Umgebung mit eingeschränktem Speicher befinden, möglicherweise keinen Speicher zuweisen können, um Ihre Ausnahme auszulösen.

    
Nathan Ernst 22.02.2012, 22:17
quelle
2

Ausnahmen sollten vor einer möglichen Erschöpfung der Ressourcen während ihres Baus schützen. Die Verwendung von dynamischen Arrays in Exceptions ist nicht gut (es sei denn, es wird durch Zeiger ausgeführt und es gibt einen Rückfallplan, wenn die Zuweisung fehlschlägt). Die Verwendung von std::string , um einige Informationen an den Benutzer zu übermitteln, ist doppelt so: Erstens ist es dynamisches Array, zweitens ist es meistens nutzlos - Funktion, die Exceptions wirft, kennt keine Umstände, um vernünftig zu erklären, warum es fehlgeschlagen ist.

Ausnahmen sollten nützliche Dinge wie Stack Tracing + Wiederherstellung von Funktionsparametern (wenn möglich) + ID zu einer externen Nachricht (z. B. dynamische Bibliotheksressource) tun, falls eine formatierte Low-Level-Nachricht für den Endbenutzer benötigt wird. Wenn Ausnahmen für den Endbenutzer gemacht werden, sollte es in Form einer kohärent formatierten Fehlermeldung von einer externen Zeichenkettentabellenvorlage (möglicherweise Hinzufügen einiger Laufzeitparameter) erfolgen. Wenn Exception verwendet wird, um das Debuggen zu erleichtern und es an den Entwickler zu machen, dann Stack-Trace, Funktionsparameter, Zustand der Maschine ist nützlich, einige hard-codierte allgemeine Zeichenfolge ist nicht.

EDIT: Es sieht so aus, als ob Sie versuchen, C ++ - Ausnahme-Wrapper um Windows-API-Aufrufe zu machen, bin ich richtig? Wenn ja, sollten Sie mehrere Dinge berücksichtigen:

  • mit _set_se_translator () um SE wie C ++ zu behandeln Ausnahmen;
  • unter Verwendung von dbghelp.dll StackWalk64 () , SymFromAddr () und ähnliche Funktionen zum Generieren von visuell lesbarem Stapel-Trace (gerade Adresse sind auch zum Debuggen von Offsite nützlich) in Ausnahmekonstruktor;
  • Verwenden eines generischen Inline-Wrappers zum Überprüfen auf Fehlerbedingung, der von der Windows-API zurückgegeben wurde und der die Ausnahme für die angegebene Bedingung auslöst oder den zurückgegebenen Wert als Rückgabetyp weiterleitet. Stellen Sie sicher, dass kein Overhead vorhanden ist (Templates + Inline + Rvalue-Referenzen eliminieren Overhead vollständig; stellen Sie auch sicher, dass Sie keine Exception direkt von der Checker-Funktion werfen, delegieren Sie sie an die Non-Inline-Funktion, um Compiler-Overhead für Funktionen zu vermeiden, die Ausnahmen explizit auslösen) .
lapk 22.02.2012 23:23
quelle
0

als Teil der privaten Daten der Klasse haben einen statischen Zeichenpuffer (erwägen Sie TLS wenn Multithreading)

what () gibt nur einen konstanten Zeiger auf diesen Puffer zurück.

in GetFormattedMessage () füllen Sie den Puffer aus (so wie Sie es gerade tun) (und eventuell von Unicode / wchars konvertieren, wenn Sie mit TCHARs arbeiten)

Als statisches Klassenmitglied wird der Puffer vor dem Auftreten einer Ausnahme im Stack vorallokiert.

Sie müssen den Speicher nicht verwalten, da er auf dem Stack zugewiesen ist. Sie kauen jedoch 1000 Bytes Stack-Speicherplatz (normalerweise keine große Sache)

es gibt jedoch nur einen Puffer für den Fehlertext, aber zu jedem Zeitpunkt sollte nur eine Ihrer benutzerdefinierten Ausnahmen existieren (denke ich?)

    
MessyHack 23.02.2012 01:41
quelle