Programiersprache für Anfänger



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



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

    Wenn man Sprachen direkt vergleicht, sollte man von gleichen Wissensstand ausgehen. Wenn man einigermaßen erfahren in den entsprechenden Sprachen ist, greift dein Argument nur bedingt.

    Und was "fehleranfälligen Pointer" angeht: Die Häufigsten Fehlermeldungen die ich aus C#/Java kenne sind die Null-Pointer Exceptions. Da man dort sehr wohl mit Zeigern arbeitet (Ja, gewisse Fallstricke werden durch eine Referenzsyntax vermieden, aber im Gegenzug eine höhere Sicherheit vorgegaukelt). Und mir ist egal ob diese dann Null-Referenz oder wie auch immer genannt wird.

    Das heißt jetzt aber nicht, das Speicherverwaltung garnicht ins Gewicht fällt.

    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.

    Da ich in den Sprachen C++/Java/C# meine Erfahrungen habe, meine Meinung (begrenze mich aber aufgrund der aktuelleren C++/C# Kenntnisse auf diese beiden im Vergleich):

    1. Framework
    In C# ist das mitgelieferte Framework umfassender und weitgehend auch leichter zu bedienen als alles, was ich von C++ kenne. Zudem ist der Stil in .Net recht einheitlich, in C++ muss man häufig für den gleichen Umfang mehrere Bibliotheken mit unterschiedlichen Stil verwenden (Auch diese Stilunterschiede kosten Zeit).

    2. Die IDE-Unterstützung
    a) Allgemein
    Ich würde sagen im Grundsatz sind moderne IDEs in allen Sprachen durchaus mächtig. Die Unterstützung wird aber auch durch Fähigkeiten der Sprache besser...
    b) Unterstützung dank Reflektion
    Was in C++ viel Analyseaufwand bei der Toolunterstützung kostet, bekommt man in Sprachen mit Reflektion teilweise fast geschenkt. Codevervollständigungen etc. die ja durchaus auch die Arbeit beschleunigen können, lassen sich leichter implementieren, was auch die Verbreitung ebensolcher Bestandteile erhöht.
    c) Bibliotheksunterstützung
    Zumeist hat man auch eine bessere Unterstützung der Bibliotheken, weil man selten externe Bibliotheken braucht. Häufig reicht in C# und Java bereits das mitgelieferte aus, wodurch die Dokumentation, die direkte IDE-Unterstützung, Grafikdesigner etc. eher zum Standard gehören als in C++.

    3. Beschleunigung dank Codereduzierung und Vereinfachungen
    Wenn ich ein und das selbe in C++ sowie C# umsetzen will, stelle ich zumindestens fest, das ich in C# meist weniger Code für die gleiche Funktionalität brauche. Es gibt hier auch Ausnahmen, aber über das Projekt gesehen gehe ich - je nach Art des Projektes - von einer Einsparung von mindestens 25% und mehr.
    Um so komplexer das Projekt ist - Grafik, Mehrschichtenarchitektur, etc., um so höher ist der Codeunterschied nach meiner Erfahrung.
    Das liegt zum Teil aber auch daran, das vieles vereinfacht dargestellt wird, weniger Sonderfälle (dafür natürlich auch einige "Stellschrauben" weniger) existieren.

    Man erkäuft sich natürlich auch Nachteile mit Java/C#. Java/C#-Programme in gleichen Funktionsumfang wie C++ Programme haben in den überwiegenden Fällen, mit den ich konfrontiert wurde, weniger Performance, höhere Speicheranforderungen, längere Startzeiten... Dies heißt aber nicht das alle Java/C#-Programme automatisch langsam sind, wobei im direkten Vergleich (zumindestens bei Standardsoftware die ich kenne), das native Programm den Vorsprung hat.

    cu André


Anmelden zum Antworten