C++ Exceptions und Relevanz



  • Könntest du eine andere Farbe für den Hintergrund verwenden? Ich hab immer noch Flecken vor den Augen.


  • Mod

    Andromeda schrieb:

    SeppJ schrieb:

    Exceptions kommen schon häufig vor im Sinne, dass fast aller Code in Ausnahmefällen Exceptions wirft. Diese passieren bloß selten.

    Made my day, du Freak. Was für ein ultrakrasser Satz. 😃

    Häufig oder selten?
    Und kommen Exceptions tatsächlich nur in Ausnahmefällen vor? LOL :p

    Wenn man nicht zwischen der Planung und der Umsetzung von Vorgängen unterscheiden kann, dann kann der Satz verwirrend sein. Für alle anderen sollte klar sein, was gemeint ist.


  • Mod

    SeppJ meint, dass Exceptions praktisch stets das Mittel der Wahl sind, um tatsächliche Ausnahmefälle abzudecken. Es ist nur so dass Ausnahmen, für die Exceptions gedacht sind, eben recht selten vorkommen sollten. Sonst wären es nicht wirklich Ausnahmen.



  • manni66 schrieb:

    Bennisen schrieb:

    Also ich finde Exceptions immer ganz hilfreich wenn Usereingaben gemacht werden. Als Beispiel wenn eine Zahl zum berechnen eingegeben werden soll aber ein String mit Buchstaben eingetippt wird.

    Das ist jetzt eher kein Fall für Exceptions.

    Echt nicht? Was wäre wenn du die eingegebene zahl dividieren willst und du aber einen string hast?



  • man prüft natürlich vorher ob die eingabe des benutzers korrekt ist für die nachfolgenden operationen



  • manni66 schrieb:

    Bennisen schrieb:

    Also ich finde Exceptions immer ganz hilfreich wenn Usereingaben gemacht werden. Als Beispiel wenn eine Zahl zum berechnen eingegeben werden soll aber ein String mit Buchstaben eingetippt wird.

    Das ist jetzt eher kein Fall für Exceptions.

    Ich denke darüber lässt sich streiten. Ich finde ein Benziner darf durchaus eine Exception werfen, wenn er mit Diesel betankt wird, und nicht nur wenn die Bremsleitung platzt.
    Bei Programmen, deren Hauptaufgabe jedoch daraus besteht User-Eingaben auf ihre Gültigkeit zu prüfen würde ich allerdings aus Design- wie auch aus Performancegründen eher abwägen.

    Finnegan



  • Finnegan schrieb:

    Ich denke darüber lässt sich streiten. Ich finde ein Benziner darf durchaus eine Exception werfen, wenn er mit Diesel betankt wird

    Das hat alle Kennzeichen eines Ortes, wo Exceptions angebracht sind.
    - Das Problem tritt beim Motor auf, und der Motor hat keinerlei Möglichkeit, das zu beheben.
    - Es gibt keine Möglichkeit, es effizient schon vorher zu erkennen (z.B. einen Dieselsensor einzubauen)
    - Wenn es auftritt, hat man ein grösseres Problem und kleine Verzögerungen sind einem dann völlig egal. Andererseits ist das auch nicht der erwartete Fall und man möchte beim losfahren nicht minutenlang warten, bis der Dieselsensor mit seiner Messung fertig ist.

    Bei Nutzereingabe ist das nicht der Fall. Falscheingaben sind Normalfall und sollen genau dort abgefangen werden, wo sie produziert werden.



  • untrusted user schrieb:

    man prüft natürlich vorher ob die eingabe des benutzers korrekt ist für die nachfolgenden operationen

    Kannst du diese Meinung begründen?



  • VerWrackt schrieb:

    Finnegan schrieb:

    Ich denke darüber lässt sich streiten. Ich finde ein Benziner darf durchaus eine Exception werfen, wenn er mit Diesel betankt wird

    Das hat alle Kennzeichen eines Ortes, wo Exceptions angebracht sind.

    Ich sage ja dass man sich darüber durchaus streiten kann.

    VerWrackt schrieb:

    - Das Problem tritt beim Motor auf, und der Motor hat keinerlei Möglichkeit, das zu beheben.
    - Es gibt keine Möglichkeit, es effizient schon vorher zu erkennen (z.B. einen Dieselsensor einzubauen)

    Ich persönlich würde da nicht gerade "die Möglichkeit haben" einen Fehler zu erkennen und ihn zu beheben als Kriterium heranziehen, sondern eher ob es sich dabei um eine definierte Funktionalität der Software handelt.
    Ist das "beheben" falscher Nutzereingaben ein "Feature" dann würde ich vielleicht so etwas wie eine "normalize"-Funktion schreiben, die aus den wirren Eingaben etwas gültiges formt, das im Weiteren nur noch via assert() geprüft wird.
    Schöpfte man immer alle Möglichkeiten zur Fehlerbehebung aus, so würde das Programm wahrscheinlich komplexer als notwendig und nicht selten furchtbar zu bedienen
    (gibt kaum etwas nervtötenderes als Software, die ständig meint zu wissen, was man eigentlich will und man erst am Schluss beim Endergebnis den produzierten Humbug vorgesetzt bekommt).

    VerWrackt schrieb:

    - Wenn es auftritt, hat man ein grösseres Problem und kleine Verzögerungen sind einem dann völlig egal. Andererseits ist das auch nicht der erwartete Fall und man möchte beim losfahren nicht minutenlang warten, bis der Dieselsensor mit seiner Messung fertig ist.

    "Erwartet" und "unerwartet" trifft es schon eher. Fehlerhafte Nutzereingaben können durchaus auch unerwartet sein, je nach dem wie man die Software spezifiziert...

    VerWrackt schrieb:

    Bei Nutzereingabe ist das nicht der Fall. Falscheingaben sind Normalfall und sollen genau dort abgefangen werden, wo sie produziert werden.

    ... die Betankung mit einem falschen Treibstoff ist schließlich ebenfalls eine falsche Nutzereingabe. Nur eben eine unerwartete. Hat man einen Dieselsensor als "Feature" wird sie zu einer "erwarteten".
    Man kann m.Mn. durchaus auch bei der Zahleneigebe Buchstaben als unerwartet definieren, je nachdem was die Software können soll.
    Vielleicht läuft sie ja sogar an einem Mini-Terminal wo es nur einen Nummernblock gibt 🙂

    Finnegan



  • Eisflamme schrieb:

    Aus der Quintessenz ging ja aber auch hervor, dass Exceptions in C++ sehr selten zu sein scheinen.

    Achtung.

    In Java und C++ und sonstwo treten Exceptions gleich häufig auf. Die grundlegende Designprinzipien sind in allen Sprachen gleich.

    In Java sind Exceptions aber "in your face". zB checked Exceptions die dir konstant vor der Nase baumeln. Das fehlende Resourcemanagement dass dich konstant zu try/finally blöcken zwingt, etc.

    In C++ sind Exception einfach im Hintergrund, denn Exception Safety in C++ passiert implizit (dank RAII). Eigentlich will man so gut wie nie ein try/catch in C++ schreiben, in Java ist try/catch an jeder Ecke zu treffen.

    Das liegt auch daran dass Exception in Java flexibler sind was Translation/Propagation betrifft und man mit einer Exception mehr machen kann als in C++.

    Aber werfen tut man gleich häufig.



  • Dann war mein Wissen da wirklich zu vage.

    Trotzdem tu ich mich schwer abzuwägen, wann ich Ausnahmen nutze oder nicht. Ich glaube, ich hatte mich damals auch schwer getan mit:

    http://www.cplusplus.com/reference/stdexcept/invalid_argument/

    Das suggeriert ja, dass man die Exception werfen sollte, wenn das Argument nicht stimmt. Das passt ja zu obigem Beispiel der Division, wenn man einen String übergibt oder so.



  • Eisflamme schrieb:

    Dann war mein Wissen da wirklich zu vage.

    Trotzdem tu ich mich schwer abzuwägen, wann ich Ausnahmen nutze oder nicht. Ich glaube, ich hatte mich damals auch schwer getan mit:

    http://www.cplusplus.com/reference/stdexcept/invalid_argument/

    Das suggeriert ja, dass man die Exception werfen sollte, wenn das Argument nicht stimmt. Das passt ja zu obigem Beispiel der Division, wenn man einen String übergibt oder so.

    Ja, wenn du einen int willst und einen string bekommst ist es ein Fehler. Bei Exception oder nicht im Fehlerfall muss man die Anwendung der Funktion abwägen. Kann man sinnvoll verhindern dass ein String übergeben wird wenn ein int verlangt ist? wenn ja, dann exception.

    Kommt es oft vor dass man einen string übergibt? dann lieber return value.

    Als Beispiel:
    File::Open() wirft eine Exception wenn die Datei nicht geöffnet werden kann.
    File::Find() wirft keine Exception wenn die Datei nicht gefunden wurde.

    Leider ist das keine exakte Wissenschaft, viel davon ist "was sich richtig anfühlt".



  • Ich würde exceptions man halt immer dann verwenden wenn man deren spezielle Funktionalität braucht?

    Also aus mehreren geschachtelten Funktionen direkt rausspringen (das passiert ja auch "selten"). "Ausnahme" heißt ja nicht unbedingt "Fehler", auch wenn sich exceptions dafür anbieten. Zum Beispiel:

    struct worker
    {
        // ...
        std::atomic<bool> stop_flag;
        struct stop_exception : std::exception {};
    
        void stop_point() { if (stop_flag) throw stop_exception(); }
    
        void run()
        {
            for (;;) stop_point(); // Thread kann hier abgebrochen werden
        }
    
        void start() 
        {
            try { run(); } catch (stop_exception &) {}
        }
    };
    

    So mach ich das (wurde mir sogar so ähnlich hier im Forum so empfohlen :D)

    Und einen thread bricht man ja nicht notwendigerweise immer in einem Fehlerfall ab, sondern z.B. wenn der Benutzer eine weitere Verarbeitung abbrechen will.



  • happystudent schrieb:

    So mach ich das (wurde mir sogar so ähnlich hier im Forum so empfohlen :D)

    Als Teil eines Scherzes hoffe ich.

    Sowas würde ich einem Mitarbeiter bei mir nicht durchgehen lassen.



  • Allgemein ist es verpönt Exceptions zu "flow control" Zwecken zu misbrauchen.

    Bei dem speziellen Thema, also Abbruch von Worker-Threads (oder generell Abbruch von lang laufenden Berechnungen), ist es allerdings "allgemein akzeptiert" das über Exceptions zu machen. Siehe z.B. ThreadAbortException oder TaskCanceledException (.NET Framework).

    Sehr praktisch sind Exceptions auch zum Abbruch von rekursiven Suchfunktionen wenn man ein Ergebnis gefunden hat (z.B. Weg aus einem Labyrinth finden). Wobei das ein Anwendungsfall ist den wohl die meisten nicht mehr akzeptieren werden.



  • Shade Of Mine schrieb:

    Als Teil eines Scherzes hoffe ich.

    Naja, eigentlich war ich schon der Meinung dass das ernst gemeint war. Hoffe ich zumindest weil ich jetzt schon mein Programm so aufgebaut habe (und bis jetzt gut damit fahre) 😃

    Shade Of Mine schrieb:

    Sowas würde ich einem Mitarbeiter bei mir nicht durchgehen lassen.

    Warum? Wenn man in der run-Methode sehr viele geschachtelte Unterfunktions-Aufrufe hat ist es doch extrem mühsam im Falle eines Abbruchs alles immer durchzureichen?

    Mit einer exception hat man dagegen eine saubere Lösung und kann sich inder Implementierung auf das wesentliche konzentrieren...



  • wenn man ein plugins system mit dlls baut, sollte man in c++ besser keine excpetions verwenden.



  • Ah, OK - für Thread Beenden ist das eine häßliche Möglichkeit die man gerne aus Bequemlichkeit verwendet. Da kann es OK sein. Es spart Code und das ist es oft Wert.



  • happystudent schrieb:

    Warum? Wenn man in der run-Methode sehr viele geschachtelte Unterfunktions-Aufrufe hat ist es doch extrem mühsam im Falle eines Abbruchs alles immer durchzureichen?

    Threads bricht man eigentlich nur ab, wenn man sie fuer spekulative Ausfuehrung braucht und sie inzwischen nicht mehr braucht. Dann frage ich sie aber ueblicherweise in der aeussersten Schleife ab und nicht so oft zwischendurch.
    Ansonsten sind exceptions in threads auch gefaehrlich, denn wenn man sich gerade in einer critical section befindet, wird zwar der lock_guard geschlossen, aber es koennen noch unvollendete Werte bestehen bleiben.



  • Marthog schrieb:

    Threads bricht man eigentlich nur ab, wenn man sie fuer spekulative Ausfuehrung braucht und sie inzwischen nicht mehr braucht.

    Und zwar immer so, dass sich ein Thread selbst beendet. Von außerhalb sollte er nur das Signal bekommen, dass er (bald) sterben soll. Einen Thread zu killen ist immer problematisch, da man nie weiß was er gerade macht.


Anmelden zum Antworten