mikrocontroller.net

Forum: PC-Programmierung Elegante weitergabe von Exceptions


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Jens (Gast)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Moin,

ich wechsel gerade (zumindest teilweise) von der Embedded 
C-Programmierung zu C++. Diese Frage gehört bestimmt zum 
Grundrepertoire.

In C habe ich bisher z.B. eine Funktion gehabt:
int irgendwas(){
}

Diese hat neben dem Ergebnis auch Fehlercodes übertragen (z.B. -1, -2, 
etc..). Wenn ich nun eine Funktion habe, die nur true/fase zurückliefern 
soll, jedoch auch Fehler weil z.B. eine Datei nicht geöffnet werden 
könnte, möchte ich das nun sinnigerweise übr try/catch lösen.

Wie formatiere ich nun elegant und praxisorientiert diese Fehler? Soll 
ich in der Funktion lauter "throws" einsetzen? Sollen diese Fehlercodes 
oder Strings zurückliefern? Und wenn ich die Funktion "irgendwas" 
aufrufe innerhalb eines try/catch blocks, gebe was mache ich mit dem 
Fehler?

Ok, was ich damit anstelle ist meine Sache (speichern, ausgeben, 
verwerfen, etc.) aber ich  frage mich, ob meine Herangehensweise richtig 
ist oder ich das Konzept nicht ganz richtig verstanden habe. Sollte ich 
z.B. Fehlercodes zurückgeben, muss ich diese wieder irgendwo definieren, 
was ich mir ziemlich umständlich vorstelle.

Danke!

Autor: DPA (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens schrieb:
> Soll ich in der Funktion lauter "throws" einsetzen? Sollen diese Fehlercodes
> oder Strings zurückliefern?

Die sollten Exceptions liefern. Am besten abgeleitet von einer von 
diesen: 
https://stackoverflow.com/questions/11938979/what-exception-classes-are-in-the-standard-c-library

Autor: sid (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
throw ist nicht schlecht
aber manchmal gibt es auch lässliche Fehler
und du möchtest die laufende Routine deswegen noch nicht sofort 
unterbrechen;
dann könntest Du eine eignene Fehlerbehandlung implementieren
wie:
void dontThrowThisErrorJustYet(int fehlercode, std::string 
fehlermeldung)

das schreibt dann zB ein Logfile oder speichert die Warnungen (sind ja 
mehr oder weniger solche) für einen späteren Gebrauch.

Gespeichertes wieder hervorzaubern zu einem günstigen Zeitpunkt kannst 
Du ja immernoch

Und die Frage ob Du code oder Meldung willst beantwortet sich relativ 
einfach
User haben sich daran gewöhnt beides zu sehen,
Informativer ist aber meist eine ausssagekräftige FehlerMELDUNG.

Ein FehlerCODE ist nützlicher für den Programmierer,
manches lässt sich innerhalb des Codes reparieren und braucht 
nichteinmal Nutzerintervention,
das kann dann über eine int leichter identifiziert werden als über einen 
string intern.

Ausserdem hilft code bei der Auffindung innerhalb des Quelltextes
(001265 .. datei 0012 Routine 6 Fehleroption 5 zB)
oder man macht sich selbst Regeln
(001265 00 user input, 12 formatting error, 6 numerical, 5 dateformat)

Was das gliedern in Tabellen und die damit verbundenen übersetzung in 
FehlerMELDUNGEN erleichtert.

Was die lieber ist und womit Du Dich wohler fühlst ist Dir überlassen.
(ich benutz mal so mal so um ehrlich zu sein)

Autor: Vincent H. (vinci)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eine der wichtigsten Grundregeln ist sich für eine der beiden Varianten 
zu entscheiden. Entweder man bleibt (z.B. wegen Performance) bei 
klassischen Fehlercodes bzw. Varianten davon (siehe std::expected) oder 
man setzt auf Exceptions.

Da Exceptions in den meisten Fällen Domain-spezifisch sind bleibt es dir 
überlassen wie du die gestaltest. Die meisten Exceptions in der 
Standardbibliothek enthalten Strings, manche Enums und manche überhaupt 
komplett andere Typen die in dem Context allerdings Sinn machen (C++20 
nonexistent_local_time etwa).

Folgender CppCon Talk fasst ganz gut zusammen worauf man achten sollte:
Youtube-Video "CppCon 2019: Ben Saks “Back to Basics: Exception Handling and Exception Safety”"

Autor: versus (Gast)
Datum:

Bewertung
-3 lesenswert
nicht lesenswert
Es gibt nur eine Grund für Exceptions, Konstruktoren bei denen ein 
Fehler auftreten kann. Alles andere kann man herkömmlich abfangen und 
sollte es auch.

Autor: Carl D. (jcw2)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Eher mittelfristig zu sehen:
Youtube-Video "CppCon 2019: Herb Sutter “De-fragmenting C++: Making Exceptions and RTTI More Affordable and Usable”"
Herb Sutter referiert über ein Konzept den Komfort von Exceptions mit 
der Performance von ErrorCodes zu vereinen. Aber vor C++23 wird das 
nichts.

Autor: Jens (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
So wie es aussieht geht hier die Meinung ja eher zum klassischen 
Fehlercode.
Packe ich dann mein ENUM mit den sprechenden Codes in z.B. meine Klasse 
unter public?

Vermutlich wrde ich es so lösen, dass gravierende Probleme als throw 
zurückgeworden werden und inhaltliche Probleme mit einem enum behandelt 
werden als normaler Rückgabewert. Ist das ein eleganter Lösungsweg?

Autor: Wilhelm M. (wimalopaan)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Jens schrieb:
> So wie es aussieht geht hier die Meinung ja eher zum klassischen
> Fehlercode.

Ich denke eher: it depends.

Mache Dir klar, was Du unter "Fehler" verstehst. Z.B. ist die leere 
Menge beim Suchen kein Fehler im engeren Sinn, sondern ein ganz normales 
Ergebnis. In dieser Art gibt es viele Operationen. Manchmal hat man die 
Möglichkeit, für diesen Fall sog. invalide Objekte zurückzugeben. Oder 
man nimmt std::optional<> und externalisiert den ungültigen Zustand des 
Objektes.

Nur bei echten, tragischen Fehlern, die auch wahrscheinlich mit geringer 
Häufigkeit vorkommen, werden dann Ausnahmen verwendet.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.