Programiersprache für Anfänger



  • 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



  • In C++ musst Du Dich weitgehen selbst um deinen Speicher kümmern, deswegen die Zeiger. Mann kann nicht ohne weiteres auf Zeiger verzichten und wenn doch, dass verschwendet man Speicher.

    Java hat eine Standard-Bibliothek. Statt Templates gibt es da Generics. Das Speicherhandling nimmt dir die Java-Runtime ab.



  • muemmel schrieb:

    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.

    Ich bin zwar beileibe kein Java- und/oder C#-Profi, aber es gibt mehrere Gründe dafür. Zum einen wohl die große Standardbibliothek, die Suche nach externen Bibliotheken beinahe überflüssig machen soll, zum anderen die bessere Tool- und Deployment-Unterstützung.

    Edit: Die automatische Speicherverwaltung würde ich nicht als schnelleren Entwicklungsgrund ansehen.



  • [quote="Badestrand"]

    muemmel schrieb:

    Edit: Die automatische Speicherverwaltung würde ich nicht als schnelleren Entwicklungsgrund ansehen.

    Ich schon! Gerade wenn man wenig Erfahrung in C++ hat, muss man sich kaum mit Memory Leaks rumärgern. Die fehleranfälligen Pointer fallen auch weg.



  • asdflllsss schrieb:

    In C++ musst Du Dich weitgehen selbst um deinen Speicher kümmern, deswegen die Zeiger. Mann kann nicht ohne weiteres auf Zeiger verzichten und wenn doch, dass verschwendet man Speicher.

    Hem, noch nie was von shared_ptr gehört, wie?

    asdflllsss schrieb:

    Java hat eine Standard-Bibliothek.

    Natürlich hat C++ keine...



  • asdflllsss schrieb:

    Ich schon! Gerade wenn man wenig Erfahrung in C++ hat, muss man sich kaum mit Memory Leaks rumärgern. Die fehleranfälligen Pointer fallen auch weg.

    Definitiv, aber wenn man die Produktivität vergleicht, dann wohl die von "ausgewachsenen" Programmierern. Und ich denke, da wird praktisch gar nicht mehr mit roher Allokierung gearbeitet und falls doch, dann ausreichend gekapselt, so dass man idR keine Speicherlecks mehr hat.



  • Badestrand schrieb:

    Zum einen wohl die große Standardbibliothek, die Suche nach externen Bibliotheken beinahe überflüssig machen soll, zum anderen die bessere Tool- und Deployment-Unterstützung.

    Hem, in real world projects braucht man aber immer eine externe Library. Wir schleppen in unseren Projekten an die 50 MByte externer JARs mit uns rum, weil die Standard-Library halt nur Standard-Klassen bietet, und man am Ende aber Software individuell entwickelt. Also suche ich mir auch meine individuellen Libs raus, egal ob es einfache Dinge wie log4j ist, oder Axis2 für SOAP, oder itext um PDF zu generieren... ich kenne bei uns kein einziges Projekt, das nicht mind. eine externe JAR hinzufügen muß.

    Und bessere Tools... was soll das sein? Es gibt gute Tools, aber wenn man natürlich noch mit VisualC++ 5.0 arbeitet (wie mir letztens ein neuer Kollege erzählt hat, weil er vorher bei SIEMENS ein C++-Projekt hatte), dann soll man auch Java-Tools von Damals als Vergleich nehmen.



  • muemmel schrieb:

    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.

    Ja, in der Theorie kannst du mit C++ fast nach jedem Paradigma programmieren. Nur läßt dich der Compiler sehr oft ins offene Messer rennen. Auch die Tatsache, daß solche Paradigmenverbiegungen gewöhnlich mit massivem Einsatz von Templates umgesetzt werden, vereinfacht die Fehlerdiagnose gerade für Anfänger nicht.

    Es kann durchaus von Vorteil sein, wenn gewisse Details nicht als Templates, sondern als Spracheigenschaften umgesetzt werden.
    Beispielsweise referenzzählende Zeiger: stattdessen in der Sprache umgesetzt werden. Wenn du in Java, einer .NET-Sprache (GC) oder Delphi (referenzgezählte Interface-Referenzen) eine Referenz falsch benutzt, sagt der Compiler dir das; in C++ landest du mit einer Fehlermeldung, die mit dem tatsächlichen Problem möglicherweise nichts zu tun hat, in der Template-Deklaration.

    Auch beim Debuggen sind Smart-Pointer ein Krampf. Jeder Step-into auf einer Zeile, in der ein Smart-Pointer benutzt wird, führt dich in den überladenen Operator -> o.ä.


Anmelden zum Antworten