Wie Programm verlassen, wenn kein Parameter zurückgegeben werden darf?



  • Wäre die Schlussfolgerung dann nicht, das Exceptions völlig überflüssig sind und es generell besser wäre terminate zu verwenden ? Warum verwendet das .Net Framework Exceptions , oder die std lib ?

    Wo ist bei der Schlussfolgerung der Denkfehler ?



  • Knuddlbaer schrieb:

    Wäre die Schlussfolgerung dann nicht, das Exceptions völlig überflüssig sind und es generell besser wäre terminate zu verwenden ?

    nö, exceptions sind schon gut, jedenfalls wenn man sofort drauf reagiert. kommt das 'catch' zu weit oben kann man u.u. den schaden nicht mehr begrenzen und muss dann das programm beenden um schlimmeres zu vermeiden...



  • Ich bekomme gedanklich ebend in diesem Zusammenhang das geschriebene von Plotzenhotz nicht zusammen , würde es jedoch gerne verstehen.

    Ich würde mich freuen, wenn Plotzenhotz sich hierzu noch mal äußern könnte, da man gerade bei gegensätlichen Meinungen oft viel lernen kann.



  • Der OP kann keine exceptions fangen. Ergo ist das werfen einer Exception Aua.



  • Hm, kann ich nix mit anfangen



  • Plotzenhotz schrieb:

    ...Weiters sollte man wissen dass das Stack-Unwinding nur dann passiert wenn die Exception auch irgendwo gefangen wird....

    😮 Das höre ich zum ersten Mal !!! Glaube es auch und habe es gerade ausprobiert (gcc 3.4.4). 😮

    GUUUT zu wissen - und seltsam, daß es mit bislang in meinem der "Expertbücher" begegnet ist. Außerdem schwer abgefahren: Ich dachte immer, Stackunwinding sei Bestandteil ein fertig compilierten Moduls. Anscheinend stellt ein Modul aber nur "Informationen" zur Verfügung, mit denen das gelinkte Modul das dann durchführen kann...
    Ich muß mir da noch ein paar Gedanken drüber machen ...

    Einerseits finde ich Deine Ausführungen recht logisch (aus individueller Entwicklersicht), andererseits aber auch (aus "Gesamtsystemsicht") für zu kurz gesprungen.
    - Wenn der Programmzustand "vermurkst" ist .... was könnte ein ausgeführter Dtor daran noch verschlimmern ?
    - in Serversystemen wirst Du massiv Ärger bekommen, wenn ein falscher Parameter (wenn man ehrlich ist: Welches größere Programm ist wirklich fehlerfrei ?) zu einem kompletten Abbruch/Restart führt.
    - terminate() ist ein absolutes "no go" für Systeme, die eine retry-Strategie unterstützen sollen.
    ...

    *grübel*

    Gruß,

    Simon2.



  • Knuddlbaer schrieb:

    Ich bekomme gedanklich ebend in diesem Zusammenhang das geschriebene von Plotzenhotz nicht zusammen , würde es jedoch gerne verstehen.
    ...

    Wenn ich das recht verstanden habe: "In bestimmten Situationen ist der Aufruf von terminate() besser als das Werfen einer exception ('besser' = zuverlässiger). Das Vertrauen auf exceptions kann einen in falscher Sicherheit wiegen."

    Gruß,

    Simon2.



  • Ich verstehe Plotzenhotz so, das es generell besser ist terminate zu verwenden.



  • Ich meine man sollte zwischen 'Exceptions' und 'Errors' unterscheiden. Eine Exception ist eben etwas was vorkommen kann und darf wenn das Programm 100% Fehlerfrei ist. Für so einen Fall würde ich NICHT vorschlagen terminate() aufzurufen - wäre ja komplett doof. Für den Fall allerdings dass etwas eintritt was nur passieren kann wenn das Programm eben NICHT 100% OK ist, man also einen Programmierfehler "gefunden" hat, in dem Fall wäre es oft schlauer das Programm abzuschiessen.

    Viele Programmierer meinen solche Fälle sollte man in Release garnicht prüfen, dafür müsse ein assert() reichen. Was ich dann wieder etwas mutig finde.

    ---

    Leider hat es sich eingebürgert in C++ von std::exception abzuleiten anstelle von std::runtime_error, daher kann man std::logic_error nichtmehr sinnvoll verwenden. Gäbe es eine Basisklasse std::error die nicht von std::exception abgeleitet wäre dann wäre die Sache besser, dann könnte man auch für einen 'Error' eine Exception werfen, und ein "vernünftiges" Programm würde einfach nie Errors fangen. Andrerseits ist da wieder "catch(...)" was diese Errors auf fangen würde - was auch wieder nicht gut ist.

    ---

    Exceptions sind eine wunderbare Sache, und ich würde niemals darauf verzichten wollen. Bloss sie für jeden erdenklichen Fehler (inklusive Programmierfehlern) zu verwenden finde ich nicht gut.



  • Ah ok, dann hatte ich das missverstanden.

    Vielen Dank für Deine Geduld 🤡



  • Plotzenhotz schrieb:

    Ich meine man sollte zwischen 'Exceptions' und 'Errors' unterscheiden....

    "Ich rieche Javafleisch !" 😉

    Nach meiner Erfahrung ist aber genau diese Unterscheidung in der Praxis das eigentliche Problem: Wann kann ich (in einer lokalen Funktion) wirklich sagen, dass eine weitere Ausführung des (gesamten) Programms keinen Sinn mehr macht ?

    Ich denke, dahier kommt auch diese generelle Exceptionverwendung ... da hat ein Aufrufer wenigstens noch die Chance, meine Einschätzung zu korrigieren. Damit will ich das nicht rechtfertigen/verteidigen, sondern nur die Entstehung erklären.

    Gruß,

    Simon2.



  • Hallo

    Der Vorteil von Exceptions gegenüber terminate ist aber, das eine Beschreibung des Abbruchsgrund bzw. relevantes Datenmaterial übergeben werden kann, was grad zum Debuggen sehr nützlich ist. Oder weißt du auf Aufhieb, welches deiner terminates grad einen Absturz ausgelöst hat, den der Benuter per E-Mail grad anmeckert?
    bis bald
    akari



  • Plotzenhotz schrieb:

    Viele Programmierer meinen solche Fälle sollte man in Release garnicht prüfen, dafür müsse ein assert() reichen. Was ich dann wieder etwas mutig finde.

    Dann definiert man halt nicht NDEBUG.

    Leider hat es sich eingebürgert in C++ von std::exception abzuleiten anstelle von std::runtime_error

    Kannst du das belegen?



  • Plotzenhotz, lol, ist klar: wenn das Laden des Plugins fehlschlaegt schiesse ich die anwendung ab. Oder wenn der User eine sonstige non-vitale operation durchfuehren will... sofort anwendung abschiessen und alle daten loeschen.

    ne ne ne ne ne ne

    das kann nicht dein ernst sein.



  • Shade Of Mine schrieb:

    Plotzenhotz, lol, ist klar: wenn das Laden des Plugins fehlschlaegt schiesse ich die anwendung ab. Oder wenn der User eine sonstige non-vitale operation durchfuehren will... sofort anwendung abschiessen und alle daten loeschen.

    ne ne ne ne ne ne

    das kann nicht dein ernst sein.

    🙄 Das ist natürlich Unsinn und hat er auch so nicht gesagt. Er hat ganz richtig darauf hingewiesen, wie eine Unterscheidung in Fehlerzustände die unmittelbar durch Programmierfehler zurückzuführen sind, und solche die unvermeidbar mit dem Programmablauf auftreten können, wie z.B. durch falsche Benutzereingaben oder ähnliches.

    In ersterem Fall (den er mit dem Label "Error" bezeichnet hat, nicht zu verwechseln mit einem Fehlercode beim Aufruf einer Systemfunktion) sollte das Programm in der Tat nicht weiterlaufen, denn die Erfahrung zeigt, dass dadurch kritische Fehler versteckt werden und u.U. noch schlimmere Folgen möglich sind.

    Der andere Fall (den er mit dem Label "Exception" versehen hat), also Fehlersituationen die ohne Programmiererverschulden im normalen Lebensalltag des Programmes auftreten können, sind hingegen eine gute Anwendung für Exceptions (wenn man sich dann auch antrainiert, exceptionfest zu programmieren, was leider nicht so verbreitet ist).

    Daher hoffe ich doch sehr, das es sein Ernst war. 😉

    Wenn es Dir nur um die verwendeten "Label" ging, wäre das ein anderer Diskussionspunkt, der aber den Rat als Solches nicht unnütz macht.



  • @akari:

    Jo, OK, Punkt. Allerdings helfen in Solchen Fällen LOGs noch besser wie ich finde. Da LOGt man dann eben vor jedem terminate() raus was der Grund war. Oder macht eine eigene "Terminate(char const*)" Funktion die das mit erledigt. Dann kann man noch den terminate Handler verbiegen (set_terminate, und den unexpected Handler mit set_unexpected gleich mit dazu) um ggf. einen Minidump/Stackdump/... abzuspeichern und DANN erst abort() aufzurufen. Der LOG und Dump Code sollte natürlich soweit wie möglich vom Rest des Programmes unabhängig sein und im Idealfall keinen globalen State haben/brauchen.

    @Shade Of Mine:

    Nein, ich schlage NICHT vor ein Programm abzubrechen wenn ein Plugin nicht geladen werden konnte. "kann nicht geladen werden" ist (egal ob Plugin/Datenfile/...) ein Fall der auch bei einem 100% Fehlerfreien Programm auftreten kann. Siehe mein Posting weiter oben wo ich das alles erklärt habe und du es (vermutlich) nicht gelesen 😉



  • Plotzenhotz schrieb:

    Nein, ich schlage NICHT vor ein Programm abzubrechen wenn ein Plugin nicht geladen werden konnte. "kann nicht geladen werden" ist (egal ob Plugin/Datenfile/...) ein Fall der auch bei einem 100% Fehlerfreien Programm auftreten kann. Siehe mein Posting weiter oben wo ich das alles erklärt habe und du es (vermutlich) nicht gelesen 😉

    ich habe es gelesen, aber du hast meins nicht genau gelesen:

    mit terminate haust du alle daten des users weg. einfach bumm weg. stundenlange arbeit fuer die katz. und das nur weil ein feature nicht funktioniert.

    oder wie entscheidest du was ein fataler fehler ist? Beispiel die rechtschreibe pruefung schmiert ab. da ist was kaputt. bei der text verarbeitung gibts ne array ueberschreitung.

    was machen? die software ist definitiv kaputt. das darf einfach nicht passieren. aber die anwendung abschiessen deswegen?

    oder andere sachen: zB ein server und ein client sendet ne kaputt anfrage und der server ist buggy -> peng, error. sofort alle anderen connections killen?



  • @Shade Of Mine:

    Ich habe deines auch genau gelesen, bloss das Beispiel was du brachtest passt überhaupt nicht zu dem was ich geschrieben hab. Was soll ich antworten wenn du von Laufzeitfehlern schreibst und ich von Programmierfehlern. Aber egal.

    Man kann Argumente für und gegen beide Varianten finden. Wer Wert auf Verfügbarkeit legt, der wird eher ne Exception werfen. Wer Wert auf Sicherheit legt wird eher das Programm abschiessen. Wer Wert auf Sicherheit und Verfügbarkeit legt sollte nach Möglichkeit einen Prozess pro Client verwenden, und den dann natürlich auch abschiessen wenn was passiert ist.

    Vonwegen verlorene Daten im Fall "Server"... blubb? Was soll das für ein Server sein der erstmal lange mit dem Client rumshakert und ihm "ok, habs gespeichert" signalisiert etc. - so dass der Client die Daten auf seiner Seite vernichtet/als übertragen markiert, und in wirklichkeit dann aber Probleme bekommt wenn er abschmiert? Ich habe selbst schon Client/Server Teile programmiert, und die kommen wunderbar damit klar wenn du den Server und/oder Client zu einem beliebigen Zeitpunkt killst.

    Vonwegen verlorener Daten im Fall "Applikation" - ja, ok, Stromausfall? Kind/Ehefrau/Hund/man selbst stolpert übers Netzkabel? Automatische periodische Backups sind in dem Fall angesagt. Funktioniert bei vielen Programmen wunderbar. Eine "gute" Applikation sollte auch nach Möglichkeit nie etwas machen wobei es schlimm wäre wenn sie mitten drin abgeschossen wird, also z.B. diverse Config/Option Files umschreiben ohne Copy-Modify-Rename ist z.B. pfui.

    Ob man eine Anwendung wegen eines solchen Fehlers abschiesst hängt wieder davon ab wie schlimm es wäre wenn das Programm ein falsches Ergebnis produziert. Wenn die ganze Tragik darin liegt dass der User auf einmal bunte Sonderzeichen am Schirm hat statt seinem C++ Programm an dem er gerade arbeitet (um ein Beispiel aus dem Leben zu greifen - die "Anwendung" ist in dem Fall Visual Studio 2005), dann ist das nicht so schlimm. Wenns aber (um beim Thema Programmier-Tools zu bleiben) um ein Source-Control System (ok, da wären wir wieder bei nem Server) geht dann würde ich ohne nachzudenken immer die "terminate()" Variante wählen. Die möglichen Auswirkungen wenn der Server mit falschen/kaputten Daten weiterläuft (und vielleicht nichtmal wer draufkommt) wären fatal.

    Guck dir mal das "Buffer Security Check" Feature vom MSVC 8 an, das macht im Prinzip genau dasselbe. Das schiesst dir nämlich auch einfach deinen ganzen Prozess unterm Hintern weg wenn eine "vermutlich überschriebene Rücksprungadresse" erkannt wurde.

    Was man dagegen in Libraries machen sollte ist eine schwierige Frage, da es ja keine brauchbare "Error" Klasse in C++ gibt...

    @Bashar:

    Leider hat es sich eingebürgert in C++ von std::exception abzuleiten anstelle von std::runtime_error

    Kannst du das belegen?

    Guck dir Open Source Projekte an. z.B. die ansonsten so coole Boost.

    class xml_unescape_exception : public std::exception
    //...
    class BOOST_FILESYSTEM_DECL filesystem_error : public std::exception
    //...
    class base64_exception : public std::exception
    

    Das sind alles Exceptions die als Folge eines reinen runtime errors fliegen können, z.B. weil ein File kaputt ist o.ä.
    Vom User z.B. als Precondition zu verlangen er muss erstmal selbst prüfen ob ein BASE64 String überhaupt gültig ist macht ja wohl kaum einen Sinn - dann kann er den gleich selbst decoden.

    Ein anderes Beispiel:

    namespace std {
    class bad_alloc : public exception
    {
    //...
    };
    }
    

    Muahaha...



  • Wenn sogar bad_alloc und boost das selbst machen, müssen runtime_error und logic_error wohl irgendein Problem haben. Wohl dass sie von string abhängen. In dem Fall kann ich es voll und ganz verstehen dass man diese Klassen meidet (auch wenn ich immer brav von runtime_error abgelitten hab 😉 )



  • Plotzenhotz: IMO vergisst du, dass Ströme in C++ gebuffert werden. Deshalb können sehr wohl Daten verloren gehen, wenn keine Destruktoren aufgerufen werden.


Anmelden zum Antworten