Programiersprache für Anfänger



  • Klassischer Schuß nach hinten 😃

    DEvent schrieb:

    Wo ist den das Problem mit einer close() Funktion/Methode?

    int main
    {
        FileStream stream = FileStream(datei_name);
        try {
            stream.write("irgendwelche Daten");
        }
        catch (...) {
            try { stream.close(); }
            catch (...) {
                openDialog("Error:", "Achtung, konnte die Datei 'foo' nicht schliessen, moeglicherweise Datenverlust. Fuehren Sie fsck aus.");
            }
        }
    }
    

    Na, zum Beispiel hast du da ein Speicherleck eingebaut (catch(...) ist nicht finally!). Wenn die Ressource, wie es sich gehört, im Destruktor freigegeben würde, wäre das nicht passiert.

    DEvent schrieb:

    Wie sieht den das ohne eine close() aus: [...]

    void realMain (void)
    {
        FileStream stream (datei_name);
        stream.write ("irgendwelche Daten");
    }
    
    int main (void)
    {
        try
        {
            realMain ();
            return 0;
        }
        catch (std::exception& e)
        {
            std::cerr << "Fehler: Exception vom Typ " << typeid (e).name () << ": "
                      << e.what () << std::endl;
            return 1;
        }
        catch (...)
        {
            std::cerr << "Fehler: Unbekannte Exception" << std::endl;
            return 1;
        }
    }
    

    So etwas enthält praktisch jedes ernstzunehmende Programm, und viele Frameworks stellen das auch automatisch bereit.

    DEvent schrieb:

    Zum einen darf man alles werfen (int, char*, Klassen, float, usw)

    In diesem Punkt stimme ich zu. Das ist nicht nur nutzlos, sondern auch äußerst hinderlich.

    DEvent schrieb:

    und zum anderen sind C++ Exceptions sowieso nutzlos, weil man den call-Stack verliert.

    Nö.

    DEvent schrieb:

    Ebenso hat C++ keine Speicherverwaltung, so das man die ehrenvolle Aufgabe hat nach einer Exception Speicherlecks zu suchen.

    Das ist, wie mein Vorposter bereits feststellte, nicht der Fall, wenn man RAII richtig einsetzt, anstatt close()-Methoden zu benutzen.

    close()-Methoden sind insbesondere in C++ eher ein Designfehler, denn sie haben einen gravierenden Nachteil: sie versetzen ein Objekt in einen Zustand, in dem der Aufruf seiner Methoden ungültig ist. Das Aufräumen sollte nur der Destruktor übernehmen.



  • DEvent schrieb:

    Wo ist den das Problem mit einer close() Funktion/Methode?

    int main
    {
        FileStream stream = FileStream(datei_name);
        try {
            stream.write("irgendwelche Daten");
        }
        catch (...) {
            try { stream.close(); }
            catch (...) { 
                openDialog("Error:", "Achtung, konnte die Datei 'foo' nicht schliessen, moeglicherweise Datenverlust. Fuehren Sie fsck aus."); 
            }
        }
    }
    

    Wie sehe der Code aus, wenn du mehr als eine Datei (bzw. andere Ressource) verwalten musst?

    Ansonsten hat audacia ja schon genug dazu gesagt.



  • DEvent schrieb:

    Exceptions in C++ ist das kaputeste was ich bis her gesehen habe.

    naja, ein bisschen kann man struppi verstehen. longjmp/setjmp passen nicht so recht zu einer sprache, die objektorientierung unterstützt und da hat er einfach ein strukturiertes gerüst darum gebaut. du solltest auch bedenken, dass die ersten c++ compiler (z.b. cfront) aus c++ c-code machten, und diesen dann durch einen c-compiler scheuchten, was einschränkungen mit sich bringt, die er beim erfinden von c++ berücksichtigen musste. irgendwann später fiel den usern auf, dass c++ exceptions im zusammenhang mit anderen konstrukten teilweise seltsames verhalten an den tag legen, aber das ist nicht nur (in c++) bei exceptions so. alles in allem ist c++ zwar nur ein 'nice try', aber, wie ich finde, können sich viele user trotzdem gut damit arrangieren (sieht man ja auch an einigen beiträgen hier).
    🙂



  • Nur mal am Rande, Struppi hat die Exceptions nicht erfunden, die gab es vorher zumindest schon in Ada.



  • die gab es schon in pl/1, also über 15 Jahre vor ada (1980)



  • selbst die CPU kennt exceptions. versuch mal durch 0 zu teilen 🙂



  • gfhgfh schrieb:

    selbst die CPU kennt exceptions. versuch mal durch 0 zu teilen

    'ne cpu kann sich sowas auch erlauben. aber stell dir mal vor, c++ würde solche exceptions auch abfangen. dann wären rechenoperationen aber höllisch lahm.
    🙂



  • C++ Exceptions sind aber bei weitem mehr als CPU Exceptions. Thema Stack-Unwinding etc.
    Die Beiden zu vergleichen ist wie einen Ziegelstein mit einem Haus zu vergleichen. Man kann einen Ziegel verwenden wenn man ein Haus bauen möchte, ja, aber an einem Haus ist bei weitem mehr dran als nur ein (oder ein paar) Ziegel.



  • Nicht nur das. CPU-Exceptions entstehen bei ungültigen Befehlen und dergleichen automatisch, die sind also eher mit Signalen zu vergleichen. C++-Exceptions werden durch throw geworfen. Man kann auch beides verheiraten, siehe Windows-SEH, muss man aber nicht.



  • Bashar schrieb:

    C++-Exceptions werden durch throw geworfen. Man kann auch beides verheiraten, siehe Windows-SEH...

    windoofs-seh ist ein ins os integriertes feature, um hardware-exceptions im eigenen programm abfangen zu können. eine sehr praktische sache übrigens, die sogar im kernel funktioniert. mit 'RaiseException' kann man das seh auch manuell antriggern (ähnlich 'throw'), aber mit c++ exceptions hat es absolut nix zu tun.
    🙂



  • Die SEH-Exceptions werden doch in C++ auf Exceptions abgebildet, oder nicht? Falls nicht, hab ich nix gesagt, ich kenn mich damit nicht aus 🙂



  • Bashar schrieb:

    Die SEH-Exceptions werden doch in C++ auf Exceptions abgebildet, oder nicht?

    ja, in den ms-compilern jedenfalls.
    🙂



  • Bashar schrieb:

    Die SEH-Exceptions werden doch in C++ auf Exceptions abgebildet, oder nicht?

    Nein, umgekehrt: die meisten Windows-Compiler implementieren Exceptions mithilfe von SEH. Mit catch (...) fängt man dennoch (ausgenommen in MSVC, und auch da nur, wenn man einen bestimmten Kompatibilitäts-Switch angibt) keine Windows-, sondern nur Sprachexceptions.

    Eine weitere Ausnahme sind VCL-Programme. Die VCL installiert einen Exception-Filter, der OS-Exceptions in Delphi-Exceptions umwandelt (mehr dazu hier).



  • Wenn der Compiler also Exceptions nicht mit SEH implementiert, könnte man dann SEH nicht mit try..catch behandeln? Wie würde das gehen, mit speziellen Handler-Funktionen?



  • Mit dem VS geht's mit __try/__catch: http://www.c-plusplus.net/forum/viewtopic-var-t-is-223116.html
    Und/Oder SetUnhandledExceptionFilter, am besten ganzen Thread durchlesen.



  • Bashar schrieb:

    Wie würde das gehen, mit speziellen Handler-Funktionen?

    dafür gibts spezielle pseudo-keyords __try, __except und __finally. das sieht dann etwa so aus:

    __try 
    {
       *(int*)0 = 1/0; // <-- crash
    } 
    __except (1)   // <-- 1 heisst: in den exception handler springen
    { 
       puts ("das wäre ihr absturz gewesen");  // <-- exception handler 
    }
    

    🙂



  • DEvent schrieb:

    Wo ist den das Problem mit einer close() Funktion/Methode?

    int main
    {
        FileStream stream = FileStream(datei_name);
        try {
            stream.write("irgendwelche Daten");
        }
        catch (...) {
            try { stream.close(); }
            catch (...) { 
                openDialog("Error:", "Achtung, konnte die Datei 'foo' nicht schliessen, moeglicherweise Datenverlust. Fuehren Sie fsck aus."); 
            }
        }
    }
    

    Hier haben wir das Problem, daß im Regenfall die Datei nicht geschlossen wird, sondern nur dann wenn eine Exception gefangen wurde. Zu dem löst Du das Problem der Close Problematik nicht, sondern gibt's nur eine Fehlermeldung aus. Diese Löung gibt es mit Destruktoren ebenfalls. Idealerweise loggt man den Fehler in eine Queue oder eine Datei weg.

    DEvent schrieb:

    Wie sieht den das ohne eine close() aus:

    int main
    {
        FileStream stream = FileStream(datei_name);
        try {
            stream.write("irgendwelche Daten");
        }
        catch (...) {
            throw();
        }
    } // hier wird FileStream::~FileStream() aufgerufen, das eine Exception wirft, weil es ein Hardwaredefekt
      // oder ein korrumpiertes Filesystem gab. Das Programm stuertzt einfach ab, weil man die
      // Exception nicht fangen kann
    

    Das ist totaler Nonsense. So macht man das bestimmt nicht.

    FileStream::~FileStream () throw () {
        int r = close (this->filedesc_);
    
        if (-1 == r) {
            openDialog("Error:", "Achtung, konnte die Datei 'foo' nicht schliessen, moeglicherweise Datenverlust. Fuehren Sie fsck aus.");
    
            // Jetzt steht einem frei das Problem zu ignorieren, zu beheben oder das Programm zu beenden.
            // Ich wähle hier den harten Weg.
            std::cerr << "Ein fataler Fehler trat auf, das Programm kann nicht mehr regulär beendet werden!\n";
            std::terminate ();
        }
    }
    
    int main {
        FileStream stream = FileStream(datei_name);
    
        stream.write("irgendwelche Daten");
    }
    

    Im Destruktor muß nur noch Geloggt werden, ob ein Fehler beim close des FileStreams auftrat. Mehr machst Du oben auch nicht. Allerdings ließt sich das untere Stückprogramm doch erheblich besser. Allerdings sollte man nicht direkt in main den eigentlichen Arbeitscode aufrufen, sondern in main einen Eception Handler reinsetzen. Wie wurde bereits von audacia beschrieben.



  • ~fricky schrieb:

    gfhgfh schrieb:

    selbst die CPU kennt exceptions. versuch mal durch 0 zu teilen

    'ne cpu kann sich sowas auch erlauben. aber stell dir mal vor, c++ würde solche exceptions auch abfangen. dann wären rechenoperationen aber höllisch lahm.
    🙂

    Warum sollte dies langsam sein? Interrupts werden schnell abgearbeitet, und nur im Fehlerfall würde der zusätzliche Code abgearbeitet.



  • ~john schrieb:

    Warum sollte dies langsam sein?

    weil vor vielen rechenoperationen abgefragt werden müsste, ob ein undefiniertes ergebnis entstehen kann (und eine arithmetic-exception o.ä. müsste losgetreten werden).
    🙂



  • Hi,

    In dem Zusammenhang mal ne Frage:
    Ich lese hier immer, daß Programmentwicklung mit C# oder Java so viel schneller gehen soll als mit C++.
    Irgendwie kann ihc mir das nicht so richtig vorstellen. Man kann doch mit C++ auch die Zeiger weglassen und (zumindest vom Aussehen her) fast identisch wie mit Java oder C# programmieren.
    Da ich mir in Java nur mal die Grundzüge angeguckt habe, kann ich dazu aber nicht allzu konkret was sagen.
    Andererseits stelle ich mir das Fehlen der STL sowie von Templates bei größeren Projekten als Einschränkung vor.
    Vielleicht kann mal ein Java- oder C#-Profi was dazu sagen.
    Danke im voraus.

    Gruß Mümmel


Anmelden zum Antworten