Alle möglichen Fehler abfangen? Auch nicht-Exceptions?



  • Ich habe lange Zeit mit .NET programmiert und wenn ich da folgendes mache:

    try
    {
        // Mein gesamtes Programm
    
    } catch(exception ex)
    {
        // Fehler abgefangen
    }
    

    dann wird jeder Fehler der in meinem Programm auftritt abgefangen. Egal was, ob ne Division durch Null, oder ne NullPointerException, Fehler beim Lesen/Schreiben von Speicher/RAM, ungültige Systemzugriffe, Fehler in DLLs die ich verwende, ein Array-Überlauf (ja ich weiß den gibts in C++ quasi nicht) und auch alle "normalen" Exceptions.
    Im Grunde heißt das, das Programm kann niemals, unter garkeinen Umständen zu einem Crash führen, egal was passiert (solange Windows stabil läuft versteht sich 😉 ).

    Die Frage ist jetzt wie ich sowas in C++ machen kann bzw. ob das überhaupt geht.
    Wenn ich sowas mache:

    int WINAPI WinMain (HINSTANCE bThisInstance, HINSTANCE bPrevInstance, LPSTR bArgument, int bCmdShow)
    {
        try
        {
            // Mein Programm
        }catch(...)
        {
            // Fehler abgefangen
        }
    }
    

    dann bekomme ich trotzdem Crashs z.B. bei Divisionen durch Null oder wenn ich so tolle Sachen mache wie int a = "hallo" (so ungefähr, ich weiß da meckert der Compiler aber ich hatte mal so einen Fall wo es richtig kompiliert hat dann aber zur Laufzeit gecrasht ist bis ich dann den Fehler gefunden hatte und das war sowas dämliches).

    Also geht das?? Oder kann ich nur "normale" Exceptions abfangen?

    PS: Bitte schlagt mich nicht, in .NET geht sowas wirklich 😃



  • Mit nem alten MS-Compiler oder wenn Du aufs alte Exceptionhandling umstellst, kannste auch wieder mit ... Schutzfehler und so abfangen.
    Aber angemessener wäre es, zu schauen, was MS heutzutage dafür vorsieht.



  • Wie kriege ich denn raus "was MS dafür vorsieht" ?

    Ich benutze übrigens Code::Blocks und programmiere ausschließlich für Windows.



  • C++User123 schrieb:

    Also geht das?? Oder kann ich nur "normale" Exceptions abfangen?
    PS: Bitte schlagt mich nicht, in .NET geht sowas wirklich 😃

    In C++ kannst du nur Exceptions abfangen. Division durch null wirft aber eben keine Exceptions. Das mag in C# anders sein. Du könntest dir natürlich ne "Integer"-Klasse schreiben die gegen solche Dinge absichert und bei Nulldivisionen etc. eine Exception wirft. Ebenso kann man leicht ne Art Smartpoitner implementieren die Nullpointer-Zugriffe abfangen und exceptions werfen statt einfach das Programm zu crashen.



  • C++User123 schrieb:

    Wie kriege ich denn raus "was MS dafür vorsieht" ?
    Ich benutze übrigens Code::Blocks und programmiere ausschließlich für Windows.

    Dann gehts wohl nicht, hast ja keine compilererweiterungen wie __except. http://msdn.microsoft.com/en-us/library/ms680657(VS.85).aspx

    Das andere Zeugs http://msdn.microsoft.com/en-us/library/ms681420(VS.85).aspx harmoniert nicht mit C++.



  • Für exceptions bieten Compiler nur eine kleine Hilfe. Seit den Anfängen der Programmierung gilt die Regel: Alle aussergewöhnlichen Ereignisse und Fehlermöglichkeiten im Programm selbst abfangen. Das zwingt zum sorgfältigem Programmentwurf und macht dieses für eine spätere Wartung stabil. Gerade bei einer Windows-Programmierung kann und sollte man von den Return-Werten Gebrauch machen. Ich selbst führe bei jedem Programm eine Protokolldatei mit, die mir jederzeit Auskunft über die durchgeführten Programmschritte erteilt. Man kann die Ausdrucke leicht auskommentieren und bei Bedarf genauso leicht reaktivieren.



  • Ich hätte auch gerne so einen "fange alle Fehler"-catch. Also so etwas wie "EndlessLoopException" oder "YourProgramDoesNotDoWhatYouWantException" oder "AlgorithmTooSlowException" oder "MyCPUDiedException" oder "UserAccidentallyRequestedTheDeleteOperation" oder "ProgrammerIsOutOfMoney" 😃 .

    Nein - echt - zum Glück werden wir Softwareentwickler noch gebraucht. Und zum Glück verlangt C++ von uns, dass wir korrekte Programme schreiben und nicht einfach NullPointerExceptions oder so etwas ignorieren können. Dadurch bekommt man langfristig robuste Programme hin.



  • tntnet schrieb:

    Nein - echt - zum Glück werden wir Softwareentwickler noch gebraucht. Und zum Glück verlangt C++ von uns, dass wir korrekte Programme schreiben und nicht einfach NullPointerExceptions oder so etwas ignorieren können. Dadurch bekommt man langfristig robuste Programme hin.

    Vollständige Zustimmung! Zum Glück dürfen wir noch denken. 👍

    P.S.: Warum kommt mir gerade UnsupportedOperationException in den Sinn? 😃



  • Nexus schrieb:

    P.S.: Warum kommt mir gerade UnsupportedOperationException in den Sinn? 😃

    Basisklasse von HeadlessException und Schwester von NegativeArraySizeException und EmptyStackException 🙄



  • volkard schrieb:

    HeadlessException

    Hehe, netter Name, da wird einem auch gleich der Aufgabenbereich klar. 🤡



  • C++User123 schrieb:

    Ich habe lange Zeit mit .NET programmiert und wenn ich da folgendes mache:

    try
    {
        // Mein gesamtes Programm
    
    } catch(exception ex)
    {
        // Fehler abgefangen
    }
    

    dann wird jeder Fehler der in meinem Programm auftritt abgefangen.
    [...]
    Im Grunde heißt das, das Programm kann niemals, unter garkeinen Umständen zu einem Crash führen, egal was passiert (solange Windows stabil läuft versteht sich 😉 ).

    Oh -- mein -- Gott.
    Das geht da tatsächlich?!? Da rasselt keine Exception durch und baut währenddessen alles zurück? Der Fehler wird erst in main() abgefangen und das Programm kehrt in seinen ursprünglichen Zustand zurück?
    Irgendwie kann ich mir das grad nicht vorstellen.
    Eigentlich sind Exceptions dazu da, möglichst nahe am Ort des Geschehens abgefangen zu werden. Dass man auch genau nachsehen kann, wo die aufgetreten ist. Exceptions sind nämlich nicht dazu da, einfach abgefangen und ignoriert zu werden, wie das in deinem obigen Beispiel geschieht...



  • catcher schrieb:

    Exceptions sind nämlich nicht dazu da, einfach abgefangen und ignoriert zu werden, wie das in deinem obigen Beispiel geschieht...

    Sie werden doch nicht ignoriert! Sie sorgen für Programmabbruch. Exceptions sind dazu da, gefangen zu werden. Spätestens in der main. Tut man das nicht, hat man "uncatched" Exceptions und die sind einfach böse in diesen Sprachen (Englisch und C++).



  • tntnet schrieb:

    .... "ProgrammerIsOutOfMoney" ....

    Klasse Idee, könnte ich sehr gut gebrauchen!



  • catcher schrieb:

    Oh -- mein -- Gott.
    Das geht da tatsächlich?!? Da rasselt keine Exception durch und baut währenddessen alles zurück? Der Fehler wird erst in main() abgefangen und das Programm kehrt in seinen ursprünglichen Zustand zurück?
    Irgendwie kann ich mir das grad nicht vorstellen.
    Eigentlich sind Exceptions dazu da, möglichst nahe am Ort des Geschehens abgefangen zu werden. Dass man auch genau nachsehen kann, wo die aufgetreten ist. Exceptions sind nämlich nicht dazu da, einfach abgefangen und ignoriert zu werden, wie das in deinem obigen Beispiel geschieht...

    Oh mein Gott (oder wer auch immer) 🙄 . Genau so ist es gerade nicht.

    Exceptions sind genau dafür da, dass ich nicht in jeder einzelnen Codezeile abfragen muss, ob ein Fehler aufgetreten ist, sondern die Fehlerbehandlung an einer Stelle sammeln kann.

    Mein main-Gerüst enthält immer ein " catch(const std::exception& e) ", wo Fehler aufgefangen werden, auf die nicht anderweitig im Programm sinnvoll reagiert werden konnte. Da gebe ich dann den Fehlertext auf cerr aus, so dass ich auf jeden Fall eine (hoffentlich sinnvolle) Fehlermeldung bekomme. Das ist schon richtig, dass man dann leider Probleme hat, die genaue Position festzustellen, aber oft ist das auch nicht notwendig.

    Natürlich werden Fehler, auf die sinnvoll reagiert werden kann, da aufgefangen, wo es Sinn macht. Das muss ja nicht der einzige catch im gesamten Programm sein.



  • Es ist mir klar, dass Fehlermeldungen in der main gecatcht auch sinnvoll sind.
    Aber das war nicht mein (einziger) Punkt. Aus dem Post geht doch hervor dass er "nur an genau einer Stelle" die exception abfängt, nämlich in der main, und danach DAS PRGRAMM WEITERLÄUFT als wäre nichts gewesen. Das kann ich 1) nicht glauben und 2) falls doch frag ich mich warum überhaupt noch exception zum catchen übergeben werden (in .net oder was er hernimmt).
    Und wenn ich eben an nur einer Stelle die Exception (als reine std::exception) abfange, kann ich auch gleich komplett durchrasseln lassen, denn ich kann maximal das what() abfragen, aber nicht das wo und das warum und den type. Und ob dem User die Meldung präsentiert wird oder ein "aborted due to uncaught exception" ist dann auch egal.
    Der Status des Programms ist nach einem catchen in der main() auch futsch, und ich muss von vorne anfangen, da ist es für den User eher hinderlich, weil der gar nicht peilt warum jetzt z.B. die ganzen eingegebenen Daten weg sind.

    Ich hoffe das war jetzt ausführliecher.



  • C++User123 schrieb:

    ...

    Grundsätzlich: Dinge wie Division durch 0 oder eine Access Violation sind keine Ausnahmen im Sinne der meisten Sprachen, sondern Meldungen des Betriebssystems. In ANSI C++ gibt es keine Betriebssystemspezifischen Ausnahmen. Hierzu muss man auf Funktionen des Betriebssystems zurückgreifen, wenn C# dies kann hast du Glück gehabt.

    Im Codegear C++ Builder wird eine Access Violation auch in eine VCL-Exception umgewandelt, das ist aber VCL-Spezifisch. Nur wird diese dann teilweise auch irgendwo "abgefangen" (Was wiederum auch nicht sonderlich toll ist).

    Der Aufwand ALLE Ausnahmen (OS-Spezifisch, als auch die normalen C++ Exceptions) zu fangen ist sehr groß. Zudem ist es ohnehin besser zu versuchen das garkeine Fehler des Betriebssystems auftreten (Auch wenn das finden der Fehlerstelle lange dauern kann).



  • catcher schrieb:

    Und ob dem User die Meldung präsentiert wird oder ein "aborted due to uncaught exception" ist dann auch egal.

    Nicht ganz. Wenn die technische Fehlermeldung z.B. in einem Logfile gespeichert wird, kann das dem Entwickler helfen, den Fehler zu finden. Zumindest viel eher als "Programm funktioniert nicht mehr".

    Ansonsten hast du natürlich Recht; Exceptions dazu einzusetzen, das Programm um jeden Preis weiterlaufen zu lassen, ist bestimmt das falsche Vorgehen.



  • Nexus schrieb:

    catcher schrieb:

    Und ob dem User die Meldung präsentiert wird oder ein "aborted due to uncaught exception" ist dann auch egal.

    Nicht ganz. Wenn die technische Fehlermeldung z.B. in einem Logfile gespeichert wird, kann das dem Entwickler helfen, den Fehler zu finden. Zumindest viel eher als "Programm funktioniert nicht mehr".

    Ansonsten hast du natürlich Recht; Exceptions dazu einzusetzen, das Programm um jeden Preis weiterlaufen zu lassen, ist bestimmt das falsche Vorgehen.

    Genau. Danke für den Hinweis. Das wollte ich auch ähnlich so schreiben. Es ist halt schon ein Unterschied, ob ein Programm mit "aborted due to uncaught exception" oder mit "connection refused" abbricht. Der technisch versierte Benutzer kann vielleicht damit was anfangen oder der Support bekommt dann doch einen Hinweis.



  • Ich muss dazu nochmal ein paar Dinge klarstellen:

    1. Natürlich läuft das Programm dann NICHT einfach weiter, sondern wird beendet. Der Unterschied ist aber dass es nicht einfach crasht sondern ich es kontrolliert beenden kann.

    2. Ja ich habe nur dieses eine einzige Catch aus folgendem Grund: siehe 3.+4.

    3. In .NET enthält die Exception Klasse auch Informationen über den Fehler, ich kann also auch in meiner Main noch aus dem Exception Objekt Infos auslesen wie: Name der Klasse in der die Ex aufgetreten ist, Name der Methode ja sogar die Zeile im Quellcode wo die Ex entstanden ist.

    4. Natürlich wäre es sinnvoll die Exception möglichst nah am Ursprung zu behandeln. Allerdings ist das in meinem speziellen Programm nicht sinnvoll, das Programm soll bei einem Fehler - egal was für einem - beendet werden. Daher habe ich nur das eine catch.

    So das erstmal dazu. Und dann finde ich es auch sinnvoll wenn sich der Programmierer Gedanken macht und keine Fehler auftreten lässt, das tue ich auch. Trotzdem können ja theoretisch immernoch irgendwann irgendwo Fehler auftreten, und für diesen Ausnahmefall hätte ich dann eben gerne diese Absicherung. Sozusagen als Lebensversicherung.

    @ berniebutt: Aber wenn das Programm crasht dann kannst du doch den Outputstream von deinem Logging nicht mehr close()-en oder?? Oder übernimmt das Windows nach einem Crash etwa selbst?



  • C++User123 schrieb:

    @ berniebutt: Aber wenn das Programm crasht dann kannst du doch den Outputstream von deinem Logging nicht mehr close()-en oder?? Oder übernimmt das Windows nach einem Crash etwa selbst?

    Nein, bei einem crash macht das Programm keinen von dir programmiertes close().
    Zumindest unter Windows bleiben die Einträge aber erhalten und können eingesehen werden. Ich mache das so und benutze keine exceptions nur nur selten debug.


Anmelden zum Antworten