Warnungen mit Exceptions?
-
Hi!
Ich bin grad dabei ne (_sehr_) kleine 3D Engine zu schreiben und hab ein paar Probleme mit Exceptions.
Beispiel: Der User fordert von der Engine, eine Auflösung von 800x700 einzustellen. Da das aber nicht möglich ist, soll die Engine die Auflösung auf einen default Wert (von 800x600) setzen. Der User soll darüber informiert werden und kann entscheiden, ob der Code weiter ausgeführt, oder abgebrochen wird.
Könnte man das irgendwie über exceptions lösen? Wenn man einmal ne Exception hat, kann man doch eigentlich (ausser per goto, was imho sehr hässlich ist) nicht mehr zurück in den try block.Ansonsten würde ich wahrscheinlich gar keine Exceptions verwenden und zurück zur C-Style Fehlerbehandlung und entweder ErrorCodes oder Funktionen a'la GetLastError() verwenden.
-
imho sollte der User eh nur auswählen können, was die graka beherrscht.
die schwachstelle ist hier imho der programmierer, wenn der beim programmieren da falsche werte einstellt, hat er ne deftige exception mit programm abruch verdient-würde sonst eh nichts bringen.
-
Wenn du eine Eingabe ablehnst, ist es schon in Ordnung, eine Exception zu werfen (und zu fangen). Wenn du dann aber zurück in den try-Block willst, stimmt IMHO was mit dem Design nicht.
Derjenige, der die Exception fängt, muss angemessen darauf reagieren (default-Auflösung, Eingabe anfordern) und kann dann die werfende Methode vielleicht nochmal aufrufen, um die neue Auflösung einzustellen (versuchen).
-
Heutzutage dürfen Spiele aus möglichst keinem Grund abstürzen, sie müssen absolut DAU-sicher sein.
Exceptions darf der User nie zu sehen bekommen weils sonst sofort wieder bei PC-Games eine auf den Deckel gibt und Kiddie das Spiel nicht kauft.
Also lieber in den catch-Block einen Log-Eintrag machen für die Profis und für alle anderen im catch-Block eine weitere Auflösung versuchen -> darum soll sich imho nicht die 3D-Engine kümmern sondern der 3D-Engine-Benützer.
MfG SideWinder
-
da im release aber so eine exception unter _gar_keinen umständen auftreten darf, kann man ruhig ne messagebox werfen-imho ist es eh unüblich, die User die Auflösung über ne art textfeld eingeben zu lassen;das zum thema dau sicher.
-
Warum darf eine Exception im Release-Modus nicht mehr auftreten? Wenn man sie brav auffängt...
MfG SideWinder
-
exceptions dürfen natürlich noch geworfen werden, aber soeine exception noch im releasecode rumzuschleppen ist wirklich unnötig
-
Wie gesagt selbst wenn der User Text eingibt lieber try&catch rumbasteln, wer weiß wie er es schafft das Programm zum Absturz zu bringen (unter Absturz fällt uA auch das Hängen bleiben für mehr als 30 Sekunden beim Einfügen von 30MB Text in ein Edit-Feld löl)
MfG SideWinder
-
ok, dieser Dau wäre echt krank, und hätte ne dicke "pösepöse" messagebox verdient
-
otze schrieb:
imho ist es eh unüblich, die User die Auflösung über ne art textfeld eingeben zu lassen
OK das ist nachvollziehbar. Wahrscheinlich werde ich das so (oder so ähnlich) lösen, wie du es Vorgeschlagen hast.
Aber trotzdem gibt es ja vielleicht in einem Programm mal einen Fall, wo man eine Warnung ausgeben will und der User kann dann entscheiden, ob das Programm weiter ausgeführt wird.
Normalerweise werden try/catch Blöcke doch nicht für einzelne Funktionen angelegt, sondern für einen ganzen Satz von Anweisungen. Um das so zu machen, müsste ich aber doch für jede Funktion einen try/catch Block schreiben.void Function() { try { Engine->SetScreenRes(800, 700); } catch(ScreenResInvalid) { Engine->SetScreenRes(800, 600); Log->LogMessage("Bildschirmaufloesung war falsch..."); } }
Das wird doch mit der Zeit sehr unübersichtlich.
Wäre in dieser Hinsicht C-Style Fehlerbehandlung nicht besser?
-
Die du aber weder mit try&catch noch mit MessageBox() irgendwie posten kannst da dein ganzes Programm hängt
Egal, für Edit-Boxen gibts ja nun bereits schlauerweise eine maximale Zeichenanzahl.
MfG SideWinder
-
otze schrieb:
exceptions dürfen natürlich noch geworfen werden, aber soeine exception noch im releasecode rumzuschleppen ist wirklich unnötig
Nö.
Exceptions sind Fehler, die man behandelt - folglich sind sie im Release Code auch noch enthalten.
asserts sind Fehler, die nicht auftreten dürfen - folglich sind sie im Release Code nicht enthalten, da wir solche Fehler bereits beim Testen entfernt haben.
Wenn ich eine Exception in der Release Version nicht mehr habe - wozu dann in der Testversion?? Dann tut es ein assert ja auch...
-
godlikebot schrieb:
Normalerweise werden try/catch Blöcke doch nicht für einzelne Funktionen angelegt, sondern für einen ganzen Satz von Anweisungen. Um das so zu machen, müsste ich aber doch für jede Funktion einen try/catch Block schreiben.
Eben nicht.
Wieso sollte man soetwas schreiben?Mal abgesehen, dass man nicht by value fängt.
Wäre in dieser Hinsicht C-Style Fehlerbehandlung nicht besser?
Exakt. Wenn du überall ein try/catch hast, dann machen Exceptions keinen Sinn. Die Frage ist aber eher: macht dein Design Sinn?
-
Du solltest keine Klasse ScreenResInvalid haben sondern eine namens engine_exception (abgeleitet von std::exception). Das "Screen Resolution was invalid." steht dann besser in .what().
Zu dem Übersichtsproblem meine ich nur: Möglichst keine Exceptions auftreten lassen. Unerwartete und tatsächlich unabfangbare Fehler (meine Engine ist zu dumm in den Fullscreen-Modus zu schalten, etc.) in einem großen try/catch-Block abfangen.
MfG SideWinder
-
Shade of Mine schrieb:
Eben nicht.
Wieso sollte man soetwas schreiben?try { WasProbieren(); } catch(...) { Reagieren(); } try { WasAnderesProbieren(); } catch(...) { AuchDaraufReagieren(); } Und so weiter
Kann man denn sagen, dass C-Style Fehlerbehandlung in C++ schlechterer Stil ist als Exceptions?
-
Shade Of Mine schrieb:
otze schrieb:
exceptions dürfen natürlich noch geworfen werden, aber soeine exception noch im releasecode rumzuschleppen ist wirklich unnötig
Nö.
Exceptions sind Fehler, die man behandelt - folglich sind sie im Release Code auch noch enthalten.
asserts sind Fehler, die nicht auftreten dürfen - folglich sind sie im Release Code nicht enthalten, da wir solche Fehler bereits beim Testen entfernt haben.
Wenn ich eine Exception in der Release Version nicht mehr habe - wozu dann in der Testversion?? Dann tut es ein assert ja auch...
assert ist für mich im code unfindbar, wenn ich auf fehlersuche bin, ein try/catch block fällt mir sofort ins auge.
-
SideWinder schrieb:
Zu dem Übersichtsproblem meine ich nur: Möglichst keine Exceptions auftreten lassen. Unerwartete und tatsächlich unabfangbare Fehler (meine Engine ist zu dumm in den Fullscreen-Modus zu schalten, etc.) in einem großen try/catch-Block abfangen.
Du meinst eine Mischung aus Exception für alle Funktionen, die "Lebenswichtig" für das Programm sind und C-Style für alles andere? Aber wäre es dann nicht ebenso gut, ganz auf Exceptions zu verzichten? Die paar kritischen Funktionen kann man ja auch auf ihren Rückgabewert überprüfen und daraufhin reagieren. Das würde auch der Einheitlichkeit der Engine dienen.
-
Nein, immer C++-Exception-Handling, aber SetResolution() wirft einfach keine Exception. Wenns nicht geht dann eben return + setzen eines Failbits, wie zB bei den C++-Streams.
MfG SideWinder
-
@SideWinder:
Was ist denn ein Failbit?
-
ios_base::iostate
typedef T2 iostate;
static const iostate badbit, eofbit, failbit, goodbit;
The type is an enumerated type T2 that describes an object that can store stream state information. The distinct flag values are:badbit, to record a loss of integrity of the stream buffer
eofbit, to record end-of-file while extracting from a stream
failbit, to record a failure to extract a valid field from a stream
In addition, a useful value is:goodbit, no bits set
Also diese werden gesetzt und können dann mit zB cin.rdstate() gelesen werden.
Die habens noch geschickter gemacht, die haben auch noch den op! überladen, der liefert rdstate()&failbit zurück:
char a; while(!cin>>a) // wenn zB ein String eingegeben wurde wird failbit gesetzt { // Fehlermeldung ausgeben oder sonstwas tun }
MfG SideWinder