Fehler markieren; Exceptions, return-Codes oder Error-Attribut?
-
Ok, danke für den Tipp ... bis jetzt kompiliert mein Beispiel noch nicht sefix!
Falls einer eine kompilierbare EigeneErrorKlasse parat hat, danke. Irgendwas passt da nicht, nichts kompiliert bei mir ich habe auch schon diverse Beipiele abgetippt und im Netz geschaut, etwa http://www.rpg-studio.de/scientia/C%2B%2B/Tutorial:_16._Fehlerbehandlung#Eigene_ExceptionklassenKomisch, mir fiel auch auf, dass da teilweise unterschiedliche Header eingebunden werden in den Beispielen, daher die Bitte nach einem kompilierbaren Beispiel.
-
Du musst <stdexcept> statt <exception> inkludieren.
-
Hilft mir nichts, brauch ein ganzes Minibeispiel, ich habe nun schon 5 Stück abgetippt, immer ist es irgendwas anderes.
-
Du könntest ja mal die Fehlermeldungen zeigen.
-
#ifndef H2RERROR_H #define H2RERROR_H #include <string> #include <iostream> #include <exception> class H2rError : public std::exception { public: virtual char const* what() throw(); }; char const* H2rError::what() throw(){ return "My Error Message"; } #endif /* H2RERROR_H */Fehlermeldung:
h2rerror.h: In member function ‘virtual const char* H2rError::what()’:
In file included from facade.h:16,
from main.h:9,
from main.cpp:4:
h2rerror.h:11: error: expected primary-expression before ‘,’ token
h2rerror.h: At global scope:
h2rerror.h:14: error: redefinition of ‘const char* H2rError::what()’
h2rerror.h:11: error: ‘virtual const char* H2rError::what()’ previously defined here
h2rerror.h:14: error: expected unqualified-id before ‘{’ tokenDas Beispiel kommt von hier http://www.rpg-studio.de/scientia/C%2B%2B/Tutorial:_16._Fehlerbehandlung#Eigene_Exceptionklassen und wenn ich das Beispiel via Copy und Paste in ein neues Projekt stelle, dann klappt das auch - jemand eine Idee?
-
Wieso zum Himmel überschreibst du what()? Finger davon!
-
Jay1980 schrieb:
const char* H2rException::what() const throw() { static std::string s; s = "H2rException ist in "; s += txt; s += " aufgetreten."; return s.c_str(); }
static std::string s;?
Wirklich?
-
Bezogen auf den zuletzt von Jay1980 geposteten Code:
Konkret fallen mir zwei Dinge auf: Erstens ist what() throw() nicht genug; die von std::exception verwendete Signatur ist
virtual char const *what() const throw();Zweitens gehört die Definition der Methode nicht in den Header, sondern in eine eigene Übersetzungseinheit, sonst kriegst du damit später Linkerfehler. Beides wird deinen Compilerfehler aber nicht auslösen, sondern würde dir erst später Probleme verursachen. Die Fehlermeldung
h2rerror.h:11: error: expected primary-expression before ‘,’ token
gekoppelt mit der völligen Abwesenheit von Kommata in deinem Code macht mich ziemlich sicher, dass sich da ein Tippfehler eingeschlichen hat, den du nicht mit herauskopiert hast.
-
Und von Exception-Spezifikationen lass lieber auch die Finger. Es gibt einen Grund, warum die seit neuestem deprecated sind.
Und vor Internettutorials hat man dich doch hier bestimmt auch schon gewarnt.
-
Naja, bis ich da auf einem grünen Zweig bin, nehme ich assert-statements und exit mit Fehlercode - gibts halt jedesmal einen Abbruch, wenn irgendwo etwas schiefläuft. Das mit dem Error-Handling scheint mir echt mühsam und tricky zu sein, gerade wenn da wohl erst vor einiger Zeit Ansätze als deprecated eingestuft wurden.
@SeppJ das heisst ich sollte nur die Exceptions der STL nutzen und keine 'eigenen' bauen sollen?
-
Jay1980 schrieb:
Das mit dem Error-Handling scheint mir echt mühsam und tricky zu sein, gerade wenn da wohl erst vor einiger Zeit Ansätze als deprecated eingestuft wurden.
Naja, die Community weiss eigentlich seit vielen Jahren dass die Exception-Specs in C++ nicht wirklich sinn machen.
Da C++11 das erste echte Update für C++ ist (C++03 war bloss ne Revision des 98er Standards), konnten sie natürlich auch erst jetzt deprecated gemacht werden.
-
Nur kann man sie in diesem Fall ja nicht wirklich weglassen, weil std::exception::what() nun mal const throw() ist (bzw. const noexcept in C++11, aber throw() ist da ja ein Alias für noexcept).
Es ist ja auch so, dass die Kritik an Exception-Spezifikationen sich vor allem gegen solche richtet, die nur bestimmte Exceptions erlauben. Die Garantie zu geben, dass überhaupt keine Exception geworfen werden kann, ist auch im neuen Standard nicht veraltet, und ob jetzt throw() oder noexcept da steht, ist erst mal von mäßiger Wichtigkeit.
-
Naja, gibt schon Unterschiede zwischen throw() und noexcept.
Bei throw() war vorgeschrieben dass unexpected() aufgerufen wird wenn doch was geflogen kommt. Und unexpected() war es wiederum erlaubt selbst Exceptions zu werfen.
Ein Programm konnte sich also nicht darauf verlassen, dass aus einer throw() Funktion niemals was rausfliegt.Bei noexcept ist es dagegen garantiert. Wenn sich das Programm nicht daran hält, dann wird terminate() aufgerufen. Und terminate() darf eben keine Exceptions werfen.
-
Jay1980 schrieb:
Naja, bis ich da auf einem grünen Zweig bin, nehme ich assert-statements und exit mit Fehlercode - gibts halt jedesmal einen Abbruch, wenn irgendwo etwas schiefläuft.
assertist okay, um Logikfehler zu finden. Aber niemals für Laufzeitfehler. Und wiesoexit()?
-
hustbaer schrieb:
Naja, gibt schon Unterschiede zwischen throw() und noexcept.
Bei throw() war vorgeschrieben dass unexpected() aufgerufen wird wenn doch was geflogen kommt. Und unexpected() war es wiederum erlaubt selbst Exceptions zu werfen.
Ein Programm konnte sich also nicht darauf verlassen, dass aus einer throw() Funktion niemals was rausfliegt.Bei noexcept ist es dagegen garantiert. Wenn sich das Programm nicht daran hält, dann wird terminate() aufgerufen. Und terminate() darf eben keine Exceptions werfen.
Das ist so nicht ganz korrekt. std::unexpected darf zwar eine Exception werfen, diese wird aber nur aus der Funktion herausgereicht, wenn sie entweder eh auf die Spezifikation passt oder die Spezifikation std::bad_exception beinhaltet, in welchem Fall die geworfene Exception durch ein std::bad_exception-Objekt ersetzt wird. Andernfalls wird std::terminate aufgerufen. So oder so kommt nichts aus der Funktion, was nicht in der Exception-Spezifikation steht. (Vgl. 15.5.2 (2) in C++03)
-
Hm, das hatte ich dann falsch aufgeschnappt, sorry.
Macht natürlich mehr Sinn so.Nochwas: bei noexcept ist glaube ich vorgeschrieben dass kein Stack-Unwinding vor dem Aufruf von terminate() stattfindet. Auch ein Unterschied zu (und IMO eine Verbesserung gegenüber) throw(), wo Stack-Unwinding vorgeschrieben ist.
-
Ich fürchte, da habe ich ebenfalls schlechte Neuigkeiten:
C++11 15.5.1 (2) schrieb:
In such cases, std::terminate() is called (18.8.3). In the situation where no matching handler is found, it is implementation-defined whether or not the stack is unwound before std::terminate() is called. In the situation where the search for a handler (15.3) encounters the outermost block of a function with a noexcept-specification that does not allow the exception (15.4), it is implementation-defined whether the stack is unwound, unwound partially, or not unwound at all before std::terminate() is called. In all other situations, the stack shall not be unwound before std::terminate() is called. An implementation is not permitted to finish stack unwinding prematurely based on a determination that the unwind process will eventually cause a call to std::terminate().
-
Nexus schrieb:
Jay1980 schrieb:
Naja, bis ich da auf einem grünen Zweig bin, nehme ich assert-statements und exit mit Fehlercode - gibts halt jedesmal einen Abbruch, wenn irgendwo etwas schiefläuft.
assertist okay, um Logikfehler zu finden. Aber niemals für Laufzeitfehler. Und wiesoexit()?Mir geht es nur darum, dass ich ein zu Ende laufen des Programms verhindern will, wenn ich merke, dass die Daten im Programm fehlerhaft sind - da dachte ich, wie ziehe ich denn am besten den Stecker und mir kam exit() und assert() - je nachdem, wie ich gerade pruefen kann. Ich habe aber nur den Thread da gesehen, http://www.c-plusplus.net/forum/210888 und exit() scheint doch nicht so der Bringer zu sein, es wäre schon besser das Programm 'sanft' aber in jedem Fall zu beenden. Bei assert muss ich aufpassen, dass mir in der Release-Version nicht automatisch die Prüfung wegfällt, daher auch keine optimale Lösung, normalerweise sollten die assert-Statements da ja draußen oder entwertet sein, wenn ich das richtig verstanden habe.
Okay, mir scheint folgender Weg als geeignet: ich werfe einfach immer exceptions, aber lege dafür eben keine eigene Exception-Klasse an. Am Ende meines catch-Blocks beende ich das Programm in dem ich nach oben weiter werfen lasse, das heisst, das irgendwann terminate() kommt und ein sanftes Ende eintritt - soweit richtig?
Code poste ich dann, wenn ich damit etwas rumprobiert habe.
-
Kann ja nicht sein, das du jetzt keine eigenen Exception-Typen definieren kannst? Das ist wirklich ganz einfach. Mach das so: leite von einer speziellen Std-Exception ab und übergebe im Ctor deinen Fehlertext. Es macht keinen Sinn what() zu überschreiben.
class my_error : public std::exception { public: my_error(const std::string &err) : std::exception(err) {}; }; throw my_error("Da ist was schief gelaufen");Hier noch ein paar Infos:
http://msdn.microsoft.com/en-us/library/t65b74ad.aspx
-
@Jay1980: Du brauchst keine Exceptions nach oben werfen. Das tut C++ für dich automatisch, wenn du sie nicht fängst. Und ne Exception fangen und danach weiterwerfen ergibt selten bis gar nicht Sinn.
@Artchi: So sah ja auch mein Vorschlag aus.