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



  • 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.



  • Wieso sollte ich das vergessen? Nein, das vergesse ich nicht. Es ist bloss nicht wichtig. Streams wird wohl hoffentlich niemand für wichtige Daten verwenden. Das wäre ja noch schöner. Und dann ist da immernoch std::flush...



  • @Plotzenhotz:

    Aeh, du speicherst daten immer total redundant und zu jederzeit sind mindestens 2 kopien der datensaetze im system sicher verstaut?

    andernfalls klappt dein abschiessen nicht. weil der client und der server ja beide sterben koennen. und da tust du wirklich immer alles sofort syncen und den ganzen mist? und die daten auch redundant halten? komplett die ganze laufzeit ueber?

    ich nicht. das ist ein enormer aufwand.

    ich kann ein programm mit einem fehler dennoch sauber beenden - zumindest so sauber wie moeglich. einfach alle daten wegzuschmeissen ist ne miese idee.

    destruktoren die handles noch offen haben, zB shared memory und aehnliches - da kann nicht immer alles geschlossen werden. log files werden nicht fertig geschrieben, etc.

    ein terminate() ist nur dann sinnvoll wenn man an einem punkt steht wo nichts mehr geht und zwar garnichts. und das kommt nie vor. also mir ist es noch nie passiert. es gibt immer sachen die man tun kann.

    was enorm wichtig ist, die daten zu sichern.

    klar kommen auch mal abschuesse vor wenn es nen hardware reset gibt und dann ist es wichtig dass die daten in einem konsistenten zustand sind. aber hier kann man auch repairs laufen lassen beim naechsten start der anwendung.

    stell dir mal nen db server vor der ab und zu sich einfach beendet. und dabei zerschiesst er jedesmal die indizes, so dass sie neu aufgebaut werden muessen. wie willst du je erkennen wo das problem liegt?

    wenn du vernuenftiges error handling machst, dann kannst du den server nach nem fatalen error sauber runterfahren. teile der anwendung sind nicht betroffen - quasi kein fehler betrifft die _komplette_ anwendung. eine anwendung besteht immer aus einzelnen modulen die interagieren. und so ein modul kann mal defekt sein. das mag sich in andere module uebertragen weil die von korrektem funktionieren der anderen module ausgehen, aber du wirst quasi nie die komplette anwendung schrotten.

    und wenn nun zB ein query an den server geschickt wird und die verarbeitung des queries schlaegt fehlt - und zwar nicht im sinne "parse error" sondern es macht echt bumm und es wird schrott geliefert. die storage engine bekommt jetzt diesen schrott query und schmiert darauf hin ab.

    muss ich jetzt den kompletten db server abschiessen? sofort. ohne fehler meldung, ohne backtrace und aehnlichem? ohne infos woran es gelegen haben koennte?

    oder sollte ich nicht lieber einen sauberen shutdown machen und sagen "ok leute, irgendwas passt mit der query verarbeitung in der storage engine nicht. die letzten x queries waren: blablabla, das problem trat bei foo in bar nach baz auf..."

    weiters beende ich die daten connetcions zu allen clients sauber und riskiere nicht dass diese irgendwelche daten verlieren weil sie mir das query schicken und nachher selber vielleicht die daten wegschmeissen.

    ich wuerde echt mal gerne wissen wie du das deinem boss erzaehlst, dass die Abteilung XY die arbeit der letzten 5 stunden verloren hat weil sie keine backups gemacht haben und dann ein fehler auftrat als jemand blaue schrift auf gelbem hintergrund machen wollte (weil da n dummer bug war der die anwendung abgeschossen hat).



  • Aeh, du speicherst daten immer total redundant und zu jederzeit sind mindestens 2 kopien der datensaetze im system sicher verstaut?

    Ich stecke Daten in eine Datenbank. Nachdem ich sie committed habe sind sie für mich "safe". Wenn der DB-Server nicht sicher genug ist (z.B. nicht geclustert) liegt das ausserhalb der Verantwortlichkeit meines Programms - lässt sich aber leicht beheben indem man einen einfachen Server in einen Cluster verwandelt. Kostet viel Geld, aber wer so krasse Ansprüche stellt muss das eben bezahlen. Macht aber bloss ein Problem wenn der DB-Server selbst ein Problem hat, was sehr selten vorkommt.

    Wenn ich mit "nicht so wichtigen" Daten arbeite spare ich mir natürlich zu gunsten der kürzeren Entwicklungszeit gewisse Dinge, sollte auch klar sein. Ob die Änderung der Schriftfarbe bei einem Terminal jetzt gespeicher wird oder nicht ist im Prinzip egal - wichtig ist bei dem Beispiel bloss dass durch einen Fehler/Abbruch nicht die kompletten Einstellungen für einen User verloren gehen (schlimm)/kaputt gehen (noch schlimmer).

    andernfalls klappt dein abschiessen nicht.

    Genau. Also klappen schon, aber es wäre nicht gut.

    weil der client und der server ja beide sterben koennen. und da tust du wirklich immer alles sofort syncen und den ganzen mist? und die daten auch redundant halten? komplett die ganze laufzeit ueber?

    Pseudocode:

    -- Client:
    while(x->haveNewData())
    {
        dataBlock = x->getNextNewDataBlock()
        socket->sendDataBlock(dataBlock)
        dataSafe = socket->recvDataSafe()
        if(dataSafe.dataId != dataBlock.getId())
            write_log(...), terminate()
        else if(!dataSafe.isSafe)
            write_log(...), whatever()
        else
            x->deleteDataBlock(dataBlock.getId())
    }
    
    -- Server:
    dataBlock = socket->recvDataBlock()
    db_connection->begin()
    if(!db_connection->haveData(dataBlock.getId()))
        db_connection->storeData(dataBlock)
    else
        // haben wir schon, können wir ignorieren
    db_connection->commit()
    socket->sendDataSafe(true, dataBlock.getId())
    

    Was daran SO viel Aufwand ist weiss ich nicht.

    (...)
    stell dir mal nen db server vor der ab und zu sich einfach beendet. und dabei zerschiesst er jedesmal die indizes, so dass sie neu aufgebaut werden muessen.

    Ja, und genau da scheinst du nicht zu verstehen worauf ich hinaus will.

    1. Ein DB Server der bei einem Powerloss irgendetwas zerschiesst was nicht zu reparieren wäre ist ein Haufen Schrott und kein DB Server. Und wenn er doch zu jedem Zeitpunkt durch einen Powerloss unterbrochen werden kann/darf ohne dass etwas passiert, dann kann er sich auch jederzeit mittels "no-cleanup-terminate" selbst verabschieden ohne dass dabei etwas passiert. Ist doch nachvollziehbar, oder?
    2. Ein DB Server der evtl. Tabellen zerschiesst oder statt einem Rollback ein Commit macht, oder einen der unzähligen anderen möglichen Fälle die "böse" wären, bloss weil irgendein Programmierfehler mit einem "versuche sauber niederzufahren" behandelt wurde anstelle eines "no-cleanup-terminate" ist ebenso ein Haufen Schrott und kein DB-Server. Du schreibst dann weiter von Modulen, und nicht alles auf einmap kaputt sein etc. - das ist schon wahr, bloss woher willst du wissen WAS noch OK ist und was nicht?

    wie willst du je erkennen wo das problem liegt?

    Indem ich das "oops.txt" File (oder wie du es auch nennen willst) checke welches der DB-Server netterweise geschrieben hat bevor er sich verabschiedete. Eine "schreibe jenes in File x.txt, flushe und schliesse das File und kille dann den Prozess" Funktion lässt sich mit vertretbarem Aufwand so implementieren dass sie funktioniert, egal wie kaputt der State des Programms schon ist. Solange du die paar nötigen Parameter noch auf den Stack bekommst, dir nicht in der Zwischenzeit ein wildgewordener Thread diese überschreibt, und die Funktion ihr HANDLE (Kernelmode Objekt und daher sicher) noch vom OS bekommt kann da eigentlich nix schief gehen.
    Und wenn der Prozess schon SO kaputt ist dass selbst das nichtmehr geht (z.B. Stack voll bis oben hin/keine HANDLEs mehr verfügbar/...), dann ist es auch schon egal, dann rettet dich sowieso nixmehr.

    und wenn nun zB ein query an den server geschickt wird und die verarbeitung des queries schlaegt fehlt - und zwar nicht im sinne "parse error" sondern es macht echt bumm und es wird schrott geliefert. die storage engine bekommt jetzt diesen schrott query und schmiert darauf hin ab.

    muss ich jetzt den kompletten db server abschiessen? sofort.

    Wenn die storage engine im gleichen Prozess läuft wie der Teil wo sie ihren Input herbekommt, dann ja. Wenn die storage engine ein eigener Prozess ist dann nein. In dem Fall meldest du einen Fehler (z.B. Syntaxfehler/...( an den anderen Prozess, und dieser soll sich selbst darauf abschiessen, da er "weiss" dass er niemals queries produziert die einen Syntaxfehler auslösen könnten.

    sofort. ohne fehler meldung, ohne backtrace und aehnlichem? ohne infos woran es gelegen haben koennte?

    oder sollte ich nicht lieber einen sauberen shutdown machen und sagen "ok leute, irgendwas passt mit der query verarbeitung in der storage engine nicht. die letzten x queries waren: blablabla, das problem trat bei foo in bar nach baz auf..."

    Ich gehe nun mal davon aus du meinst den Fall storage engine und das defekte Modul leben im selben Prozess (siehe oben).
    Ich habe schon geschrieben dass es Sinn machen kann a) den terminate Handler zu verbiegen und b) diverse Infos zu loggen bevor man dem Prozess den Todesstoss versetzt. Das ist *eine* Sache. Eine *andere* Sache ist es sich darauf zu verlassen dass das komplette Stack-Unwinding noch gut geht. Das ist IMGO bei einem wirklich wichtigen Projekt nicht nur ziemlich mutig sondern eher fahrlässig.

    Wenn alle Programmteile/Module/Prozesse/... sauber zusammenarbeiten gehen dabei (=beim Prozess abschiessen) auch keine Daten verloren. Da sie eben noch nirgends gelöscht sind wo sie "entstanden" sind/zwischengespeichert wurden aber noch nicht "safe" weitergegeben wurden. Wenn sie "safe" weitergegeben wurden dann hat sie eben ein anderes Modul.

    weiters beende ich die daten connetcions zu allen clients sauber und riskiere nicht dass diese irgendwelche daten verlieren weil sie mir das query schicken und nachher selber vielleicht die daten wegschmeissen.

    Ein Client der Daten verliert weil er ein "connection reset by peer" bekommt anstelle der "is ok jetzt, habs weggesichert" Meldung vom Server ist ein Haufen Schrott und kein Client. Ganz einfach deswegen weil es SO oft dazu kommen kann dass irgendwo eine Netzwerkverbindung flöten geht.

    ich wuerde echt mal gerne wissen wie du das deinem boss erzaehlst, dass die Abteilung XY die arbeit der letzten 5 stunden verloren hat weil sie keine backups gemacht haben und dann ein fehler auftrat als jemand blaue schrift auf gelbem hintergrund machen wollte (weil da n dummer bug war der die anwendung abgeschossen hat).

    Siehe oben. Wenn die Daten wichtig sind gehen sie nicht verloren. Wenn doch hat ein Programmierer scheiss gebaut oder sich nicht an die Vorgaben gehalten - das selbe Problem kann man aber immer haben, ganz unabhängig davon ob man sich nun an "terminate()" oder "throw" hält.

    ---

    Ein neuer Grund gegen "throw" (für "solche Fehler" wo wir uns ja nunmehr einig sind was "solche Fehler" bedeutet): alles was man werfen kann kann man auch fangen (catch(...)). Das kombiniert mit der Tatsache dass z.B. in vielen Libs an diversen Stellen "catch(...) {}" Blöcke vorkommen ... ist nicht so gut wenn ich was werfen will was bis nach main() durchgeht und dort dann zu exit(99) o.Ä. führt.

    Noch ein Grund: Multithreading. Wie teile ich allen Threads mit sie mögen bitte "throw critical_error();" machen? Shared state ist nunmal shared state, und der kann genauso kaputt sein - was dann alle Threads betrifft, womit wir schon die Notwendigkeit haben alle zu beenden.



  • Plotzenhotz schrieb:

    Indem ich das "oops.txt" File (oder wie du es auch nennen willst) checke

    leider nicht moeglich da vernuenftige infos rein zu schreiben, weil du im terminate handler kein stack unwinding hinter dir hast - du hast also 0 ahnung vom kontext wo der fehler aufgetreten ist.

    waehrend ich mit meiner exception ne bessere funktionalitaet habe: weil eben mehr infos zur verfuegung stehen um ein logfile zu schreiben. weiters werden destruktoren verlaesslich aufgerufen und ich kann entscheiden ob der fehler fatal genug war um einen sofortigen shutdown zu rechtfertigen.

    sachen die ich mit terminate nicht kann.

    terminate bringt mir keine zusaetzlichen features die mir eine exception vorenthaelt.

    du schreibst korrekterweise: woher weiss man was alles kaputt ging: tja, vielleicht weiss ich es ja. vielleicht ist es eine grosse anwendung die sachen macht die unabhaengig voneinander sind. beispiel: webserver. wenn das modul zur verarbeitung von PHP code abschmiert, dann ist es nicht zwangslaeufig noetig auch die perl und python module abzuschalten. uU aber doch. ich entscheide das einfach spaeter und bleibe flexibel und kann mich immer umentscheiden. vielleicht will ich alle dynamischen sachen abdrehen und nur noch statische seiten liefern wenn ein fehler aufgetreten ist.

    vielleicht habe ich aber ein gutes sandbox model und kann es mir leisten einfach das kaputte modul neu zu initialisieren und den vorfall nur zu loggen.

    alles moeglichkeiten die ich mit terminate nicht habe.
    ein terminate schiesst mir den ganzen server ab - egal ob es das ist was ich will. das eine modul kann nie soviel ueber die komplette anwendung wissen um so eine entscheidung faellen zu koennen.

    nicht alle modul-fatelen fehler sind anwendungs-fatal.
    wie gesagt: hintergrundfarbe in einem word dokument aendern: das modul "ColorChooser" schmiert ab. Wilder zeiger irgendwo. muss ich jetzt wirklich das dokument killen? oder soll ich nicht lieber vorher noch schnell einen versuch starten es zu retten?

    du bist mit terminate auf ein "bumm schluss aus" festgelegt. mit exception kannst du genau so ein "bumm schluss aus" machen, wenn es sinn macht - aber gleichzeitig kannst du auch den fehler korrigieren wenn das mehr sinn machen sollte. du hast mehr infos ueber den kontext des fehlers. und es gibt resourcen die dein OS dir nicht schliessen kann - die du uU schon freigeben solltest.

    es ist einfach so: exception bieten _mir_ die moeglich zu entscheiden ob ich _meine_ anwendung abschiesse. Waehrend ein terminate mir diese entscheidung weg nimmt und ich mich ploetzlich auf diese 3rd party code verlassen muss das die entwickler genug ahnung von meiner anwendung haben um die richtigen entscheidungen zu treffen.

    finde ich sehr fragwuerdig.

    PS:
    was du von den redundanten daten gesagt hast: du brauchst fuer sowas transaktionen wenn du die komplexen daten auf dem server stabil halten willst.
    ein gaengiges transaktionsmodell fuer c++ basiert auf RAII -> und das verlangt dass der dtor aufgerufen wird 😉 dh, du hast inkonsistente daten nach dem terminate. moeglich diese zu reparieren, aber wenn ne exception fliegt ist das reparieren nicht mehr noetig - weil es n automatisches rollback der transaktion gibt.



  • @Shade Of Mine:
    Ja, ich weiss nicht was ich noch alles schreiben soll. Ist eigentlich so einfach und ich habs jetzt mehrfach erklärt. Du schreibst selbst "Wilder zeiger irgendwo." - was willst du mehr? Wieso gehst du davon aus dass mit diesem wilden Zeiger nicht einfach *irgendwas* überschrieben wurde, zum Beispiel lebenswichtige Daten für die Module die du noch für "gut" hältst. Oder "das Dokument". Eine 0 an die erste Stelle und du speicherst ein leeres Dokument. Toll. Grosses Kino. Viel Spass mit deinen Exceptions.


Anmelden zum Antworten