std::exception und die Kinder



  • aber ist der Exceptionwurf nicht genau die Behandlung der Falscheingabe?

    Exceptions haben was mit Ausnahmen zu tun voellig losgeloest von Eingaben.



  • Bashar schrieb:

    Warum? Was insbesondere ist an der Aufteilung in Logik- und Laufzeitfehler schlecht?

    In welchen Situationen kann man std::logic_error denn sinnvoll einsetzen? Das einzig Vernünftige, was man damit tun kann, ist das Programm sofort zu beenden und einen Log o.Ä. zu schreiben. Nach einem Logikfehler sollte man aber nicht weiterarbeiten.

    Ist für mich halt eher ein Fall von assert...



  • Logikfehler werden koennen weiter spezifiziert werden durch domain_error, invalid_argument, length_error, out_of_range, future_error. logic_error ist also genau dann sinnvoll, wenn es so aehnlich wie dessen Ableitungen ist, diese es nicht ganz treffen.

    Nach einem Logikfehler sollte man aber nicht weiterarbeiten.

    Koennen muessen sollen ... ist vom Anwendungs- und Problemfall abhaengig.

    Das einzig Vernünftige ... das Programm sofort zu beenden

    Bullshit.



  • logik0r schrieb:

    Ist für mich halt eher ein Fall von assert...

    assertions haben im Release-Modus keine Wirkung.

    BTW, sollte das eine Antwort auf meine Frage sein? Wenn du der Meinung bist, dass Logikfehler als Exceptions sinnlos sind, dann ist doch nicht die Aufteilung der Exceptionhierarchie schlecht, sondern gerade gut. Du kannst den Zweig logic_error dann ja einfach ignorieren.



  • Was sind für euch Logikfehler? Für mich sind Logikfehler Bugs.

    Etwas, das im Release-Modus nicht vorkommt. Und vor allem etwas, das man nicht sinnvoll zur Laufzeit behandeln kann -- wenn die Programmlogik fehlerhaft ist, wie soll man dann noch weiterarbeiten? Jeder weitere Schritt basiert auf fehlerhaften Annahmen. Man läuft Gefahr, noch mehr Schaden anzurichten, wenn man den Fehler ignoriert. Daher würde ich versuchen, was möglich ist zu retten, und das Programm zu beenden.


  • Mod

    logik0r schrieb:

    Daher würde ich versuchen, was möglich ist zu retten, und das Programm zu beenden.

    Und wie machst du das? Sicherlich nicht, indem du den Fehler ignorierst oder mittels assert ein exit auslöst, sondern indem du eine Exception wirfst, die gefangen wird und einen geregelten Abbruch auslöst.



  • @SeppJ
    Nein, eben gerade nicht.
    Man will eigentlich einen nicht-ganz-so-geregelten Abbruch.
    Ideal wäre die Exception gar nicht zu fangen.

    WENN man denn überhaupt abbrechen will.

    @logik0r
    Die Argumentation ist so alt wie das Thema Fehlerbehandlung in Programmen.
    Der Standpunkt ist nicht unsinnig. Er ist aber auch nicht der einzige der Sinn macht. In vielen Fällen ist es besser das Programm fortzusetzen.



  • Also ich finde "falsches Argument ist ein Logikfehler" nicht konsistent durchdenkbar.

    Demnach sollte eine invalid_argument-Exception nicht ausgelöst werden, wenn der Benutzer irgendwas eingibt?
    ~~
    Wenn mein XML-Parser also eine invalid_argument-Exception wirft, weil der Benutzer in der Datei rumhantiert hat (was er darf!), aber einen Fehler gemacht hat, dann ist das nicht legitim? Analog zur Wurzelfunktion müsste ich ja hier vorher alles prüfen, damit die Exception nicht geworfen wird, weil die ja sagen würde "falsches Argument" und damit ein Logikfehler wäre. Oder habe ich einen Denkfehler?~~

    std::streams kann man so einstellen, dass die bei Falscheingabe eine Exception werfen.

    int x;
    std::cin >> x;
    

    Benutzer gibt "Hund" ein, Exception fliegt => Das ist aber ein runtime_error. Vom Namen her wäre invalid_argument doch die perfekte Basisklasse. Oder ist "Hund" in dem Kontext kein Argument? Dann finde ich aber invalid_argument als Namen irreführend.


  • Mod

    Eisflamme schrieb:

    Oder ist "Hund" in dem Kontext kein Argument?

    Argumente sind das, was an Funktionen übergeben wird, nicht die Zeichen in irgendeinem Stream. Hier also das x.



  • Dann nehme ich doch wieder mein Beispiel mit der XML-Datei. Die lese ich einen string, den übergebe ich meinem Parser. Parser merkt "das ist grober Unfug" und schmeiß ne Exception. Wäre die Exception vom Typ invalid_argument, wäre das für mich vom Namen her korrekt, weil das Argument mit dem Inhalt "XML-Datei" invalide war.

    Wäre aber trotzdem basierend auf Benutzereingabe, hat nichts mit einem Logikfehler der Software zu tun.


  • Mod

    Ist doch egal, woher der Inhalt der Zeichenkette kommt. Letztendlich war das Argument "grober Unfug", das Durchführen der Aktion logisch unmöglich. Der runtime_error zeigt hingegen an "Upps, das sah eigentlich richtig aus, hat aber trotzdem nicht funktioniert".



  • Man läuft Gefahr, noch mehr Schaden anzurichten, wenn man den Fehler ignoriert. Daher würde ich versuchen, was möglich ist zu retten, und das Programm zu beenden.

    Niemand redet von Ignorieren, Abbruch ist die letzte Option, aber nie die einzige. Ein konsistenter Zustand der Anwendung ist bei vielen Programmen gefragt, erst wenn dieser nicht mehr hergestellt werden kann, dann ist ein koordinietes Beenden sinnvoll.



  • Achso. Ich dachte, logical_error hieße, dass die Software einen Logikfehler enthält, nicht etwa dass eine Aktion logisch nicht möglich durchführbar ist. Natürlich sind asserts für ersteres da.

    Nagut, dann... puh, ich weiß nicht, ob ich die Unterscheidung so toll finde. Schließlich ist logical_error ja auch ein Fehler, der zur Laufzeit geschieht, somit eine Art "runtime_error", auch wenn das Wort es nicht bedeutet.

    Mir fällt nicht Besseres ein, aber mir erscheint das einfach überhaupt nicht intuitiv... mein Problem 😉


  • Mod

    Das ist ja auch so eine Art logischer Fehler in der Software, wenn so etwas auftreten kann. Sie hat so geschrieben zu sein, dass unmögliche Aktionen gar nicht erst durchgeführt werden.



  • Find ich nicht. Wenn der Benutzer mir eine malformed XML-Datei eingibt, fliegt dadurch eine Exception, die fange ich und weiß dadurch, dass sie korrupt ist. Dann kriegt der Benutzer eine entsprechende Meldung und das Programm läuft weiter, als hätte man die Datei noch nicht geladen.

    Wieso soll ich da einen großartigen XML-Check vorsetzen? Regel ist, dass die XML-Datei in Ordnung ist. Ausnahme, dass etwas daran kaputt ist, weil der Benutzer Fehler gemacht hat.

    Es ist einfach unnötiger Aufwand irgendwelche Checks drumherum einzubauen, wenn der Parser das selbst macht und mir das mit einer Exception mitteilt. Mehr Code, der fehlerhaft sein kann und der einfach unnötig ist. Genau so sehe ich nicht, wieso ich bei einer Wurzelfunktion nicht einfach die Exception fangen kann, dem Benutzer die Ausgabe gebe, dass das Argument invalide ist und der Ablauf weitergeht... Wo ist das Problem?



  • @Eisflamme
    Einen "logic error" mit einer Exception statt ASSERT/abort/... zu behandeln kann oft in Interfaces zwischen zwei Programmteilen Sinn machen.

    Denk nur mal an Betriebssysteme.

    Ich denke die wenigsten Leute hätten viel Freude damit wenn das OS sämtliche "logic errors" mit einem BSOD bzw. auch nur dem Abbruch des Prozesses quittieren würde.
    Beispielsweise wenn man einen IOCTL an ein Gerät schickt das diesen gar nicht unterstützt.
    Oder wenn man versucht in ein File zu schreiben das man nicht schreiben darf.

    Das sind Dinge die ein Programm immer vermeiden könnte, aber oft ist es besser es einfach zu probieren und dann zu sehen was passiert. Weil es oft viel unkomplizierter umzusetzen ist, und unkomplizierter ist besser als komplizierter.

    Natürlich kann man jetzt sagen dass alles was "von ausserhalb" kommt erstmal validiert werden müsste. Aber es ist oft einfach nicht praktikabel alles vorab erstmal zu validieren. Es ist oft viel praktischer in der Schicht die die Requests von Ausserhalb entgegennimmt nur bestimmte grundlegende Dinge zu validieren, und den Request dann an einen anderen Programmteil weiterzureichen.
    Wenn der dann aber sämtliche "invalid argument" Fehler mit ASSERT/abort quittiert, hat man ein Problem.

    mMn. muss man in jedem Fall einzeln entscheiden ob es OK ist bei einem bestimmten Fehler eine Exception zu werfen, oder ob es doch besser wäre den Prozess einfach abzubrechen.



  • Wieso soll ich da einen großartigen XML-Check vorsetzen? Regel ist, dass die XML-Datei in Ordnung ist. Ausnahme, dass etwas daran kaputt ist, weil der Benutzer Fehler gemacht hat ... wenn der Parser das selbst macht und mir das mit einer Exception mitteilt

    Nein, Exceptions werden normalerweise nicht fuer diese Art Ausnahmen benutzt. Normalerweise gibt der Parser den Fehler beim Parsen nicht durch eine Exception nach aussen weiter. Bedenke: C++ ist nicht Java, wo dass vielleicht ueblich ist. Exceptions werden fuer unvorhersehbare Dinge benutzt und nicht fuer den Kontrollfluss. Beispiel Netzwerkverbinding: Eine Ausnahmesituation ist, wenn eine bestehende Netzwerkverbindung waehrend einer Transaktion gekappt wird indem der Netzstecker gezogen wird. Selbst dann muss nicht auf Exceptions zurueckgegriffen werden.

    Beispiel fuer logic_error: Dynamische Datentyp, der sowohl Strings und Zahlen repraesentieren kann. Operationen auf diesen bspw. + sind nur partiell definiert.



  • hustbaer:
    Okay, verstehe ich!

    knivil:
    Das verstehe ich auch, wobei ich es immer noch schwierig finde die Grenze zu ziehen. Unvorhergesehen ist ja im Grunde nichts, wenn man dafür eine Exception bastelt, denn dann hat man ja dran gedacht. Dein Beispiel für logic_error finde ich gut. 👍 Hm, aber für mich ist ein Ausnahmefall auch nur ein anderer Zweig eines Kontrollflusses. Wie gesagt: Meine XML-Datei wird ja eigentlich immer korrekt geparst. Dass die invalide ist, ist für mich unvorhergesehen (zu einem gewissen Maße, siehe Satz 2).

    Auch glaube ich dann bei vielen Bibliotheken Konflikte zu sehen. Also RapidXML schmeiß eben in dem Szenario eine Exception, ist das dann "falsch"? Und bei std::cin kann man bei Bedarf auf fehlerhafte Benutzereingabe eine Exception werfen lassen, das ist für mich aber auf derselben Ebene wie eine XML-Datei-Eingabe: wenn der Benutzer bei einer Zahlenerwartung einen String eingibt, ist das für mich genau so Kontrollfluss (oder Ausnahme, je nach Standpunkt) wie bei einer malformed XML-Datei. Dann wäre hier eine Exception ja auch nicht angebracht?



  • ist das dann "falsch"?

    Sicher nicht. Finde ich es gut: Nein. 🙂 Klar kann man sagen, ist Geschmackssache. Aber manche haben halt einen schlechten Geschmack. 🙂 Wer definiert guten Geschmack? Hmm, die C++-Community wahrscheinlich.

    Unterschied zwischen Benutzereingabe und XML-Datei: Benutzer verschreibt sich viel oefter als dass eine maschinengenerierte XML-Datei fehlerhaft ist. Deswegen ist es legitim, auf Fehler unterschiedlich zu reagieren.

    Auch glaube ich dann bei vielen Bibliotheken Konflikte zu sehen

    Nun, viele Bibliotheken schmecken eben nicht gut. Aber nicht immer kann man sich ein Gericht von einem 3-Sterne-Koch leisten.



  • Ja, nur manchmal kann der Benutzer auch manuell die XML-Datei ändern. Wollen die meisten bei mir nicht, aber kommt vor. Aber gut, ich sehe schon, die Grenze ist verschwommen.

    Macht das boost für Deinen Geschmack gut? Irgendworan muss man sich ja ein Beispiel nehmen.


Anmelden zum Antworten