Exceptions in C++ hui oder pfui?



  • dot schrieb:

    Also ich find #pragma comment(lib, "bla") ist eine wirkliche Unart. Sowas hat im Source-Code nun wirklich nichts zu suchen, das ist Aufgabe des Buildsystems.

    Wenn Ihr dann wenigsten //#pragma comment(lib, "bla") in die Datei schreiben würdet! Dann konnte man sich das zusammenklauben und im Build-System eintragen. Aber das ist nicht der Fall.



  • Wieso sollte ich das machen? Ich verwend einfach ein vernünftiges Buildsystem...



  • dot schrieb:

    Wieso sollte ich das machen? Ich verwend einfach ein vernünftiges Buildsystem...

    Also nicht MSVC?
    Weil die benötigten Libs direkt von den inkludierten Headers abhängig sind (oder gemacht werden können), dann kann ich das #pragma(lib auch in den Header schreiben und der Header ist dann sogar in dieser Hinsicht self-sufficient.
    Socketklasse in anderem Projekt benötigt? Null Problemo. Durch das inkludieren der Socket.hpp weiß ich ja automatisch, daß die ws2_32.dll dazugelinkt werden muß. Es ist halt einen kleinen Schritt weiter, als nur in die Socket.hpp zu schreiben "Lieber Benutzer! Diese Datei und die zugrörige *.cpp benutzen Funktionen aus der ws2_32.dll. Vergiß nicht, in den Linkereinstellungen einzustellen, daß die ws2_32.lib dazugelinkt werden muß.".
    Und ich nezweifle jetzt auch, daß Dein Build-System das macht, sondern ich nehme an, Du hast einen Haufen von libs, die dazugelinkt werden, aber hast keinen Bezug mehr, warum welche lib benötigt wird und wenn Du Dateien fremdgehen lassen willst, bemerkst Du, daß Dir solche Kommentare durchaus fehlen.
    Wobei ich im Kopf habe, warum ich welche libs dazugenommen habe. Aber wie lange? Und kann mein Nachfolger Gedanken lesen? Also ich kann jedenfalls die Gedanken meiner Vorgänger nicht lesen.



  • volkard schrieb:

    Also nicht MSVC?

    MSVC ist kein Buildsystem. VCBuild war mal eines und MSBuild ist eines und letzteres verwend ich. Schonmal was von Property Sheets gehört?



  • pumuckl schrieb:

    314159265358979 schrieb:

    @Topic: Eindeutig pfui. Ich bin die ganze try-catch-Scheiße leid.

    pumuckl schrieb:

    Das Wichtigste zum Umgang mit Exceptions ist allerdings die Aussage, dass exceptionsicherer Code nichts mit andauerndem try/catch zu tun hat. Leider verstehen das viele Leute immernoch nicht.

    Das hast du nun aber falsch verstanden. Nochmal besser formuliert: Ich bin es _generell_ leid, try-catch zu verwenden, weil die Syntax so unglaublich umständlich und hässlich ist. Das heißt nicht, dass ich's dauernd verwende 😉



  • dot schrieb:

    volkard schrieb:

    Also nicht MSVC?

    MSVC ist kein Buildsystem. VCBuild war mal eines und MSBuild ist eines und letzteres verwend ich. Schonmal was von Property Sheets gehört?

    "Property Sheet" kann alles bedeuten. Vermutlich ist damit ein Property Sheet gemeint.
    http://msdn.microsoft.com/en-us/library/windows/desktop/bb774538(v=vs.85).aspx

    Ich fürchte, Du willst mir jetzt was verkaufen, wie man mit grafischen Dialogen was erreichen kann, was als eine Zeile Code viel besser gelöst wäre.



  • Nö, ich mein eigentlich das: http://msdn.microsoft.com/en-us/library/a4xbdz1e.aspx
    Damit kann beispielsweise jeder Entwickler des Teams an bekannten Orten (z.B. MSBuild Extensions Directory) Property Sheets für alle möglichen Versionen aller möglichen Libs und SDKs die er so installiert hat ablegen.
    Ein VC++ Projekt verweist dann einfach auf die entsprechenden .props Dateien der benötigten libs und fertig. Damit kann jeder Entwickler seine Dateien organisieren wie er will und auch 100 verschiedene Versionen aller möglichen libs halten und trotzdem funktioniert jedes Projekt einfach so out of the box. Da muss ich dann weder irgendwelchen Code irgendwohin kopieren noch irgendwelche libs irgendwo eintragen. Und nur weil Visual Studio selbstverständlich eine GUI zum Editieren von Propery Sheets bietet, heißt das noch lange nicht, dass ich auf die angewiesen bin. Die GUI ist doch nur ein bequemes Interface zum Buildsystem.
    Mit deiner Zeile Code wär das imo überhaupt nicht besser gelöst, denn das pragma ist plattform-/compilerspezifisch und kommt mit verschiedenen Versionen, Suchpfaden, etc. rein prinzipiell schon nicht klar. Sowas gehört eben einfach nicht in den Code, genau für sowas gibts doch überhaupt erst ein Buildsystem...



  • pumuckl schrieb:

    pumuckl schrieb:

    asserts mag ich auch nicht unbedingt. Schließlich gibts unit-Tests, die ein Interface breit genug testen sollten.

    Hä??

    Ich nutze keine Assertions. Wozu auch? Wenn ein assert sicherstellen würde, dass die Eingaben in eine Schnittstelle bestimmte Kriterien erfüllen, dann stelle ich in meinen Unit-Tests sicher, dass die aufrufenden Funktionen die Schnittstelle immer mit ordentlichen Eingaben bestücken. Wenn ein assert sicherstellen würde, dass ich von irgendwo ordentliche Rückgabewerte bekomme, teste ich das genauso über Unit-Tests, Regressionstests usw.

    [/quote]
    Die Logik kann ich beim besten Willen nicht nachvollziehen. Wenn du auf Assertions verzichtest um gewisse Zusicherungen zu überprüfen, wie willst du das mit einem Test prüfen? Willst du evtl. sagen, dass du keine Assertions brauchst, weil deine Tests alle durchlaufen und damit Programmierfehler die Assertions auslösen könnten ausgeschlossen sind? Aber das würde doch eine Testabdeckung von 100% voraussetzen.



  • [QUOTE=seldon]

    eine Exception würfe, wenn der Benutzer "abc" eingibt1. Es könnte aber programmabhängig sinnvoll sein,

    int x;
    std::cin >> x;
    

    eine Exception würfe, wenn der Benutzer "abc" eingibt1. Es könnte aber programmabhängig sinnvoll sein,

    program_options parse_config_file(std::istream &cfg_file) {
      ...
      if(!(cfg_file >> node_id)) throw malformed_config_file("node_id muss angegeben und numerisch sein");
      ...
    }
    

    zu schreiben, denn man kann durchaus den Standpunkt vertreten, dass eine kaputte Konfigurationsdatei den Rest des Programms in der Regel am Weitermachen hindern wird.

    Das bedeutet durchaus nicht, dass eine Exception unbedingt zum Programmende führen muss, aber wenn ich eine Exception werfe, habe ich die Vermutung, dass ein größerer Programmteil durch die Ausnahmesituation, auf die ich gestoßen bin, abgebrochen werden müssen wird.
    [/QUOTE]

    Wenn man eine fehlerhafte Konfigdatei oder Beispiel aus der Praxis, ein Savestand nicht geladen werden kann, dann kann man das aber auch ganz gut als Teil des Programms behandeln.

    Also nen ganz normalen

    if() ...else
    

    Block nehmen und den Fehler dann im else Block als Teil des normalen Programms behandeln.

    Wozu brauche ich da also ne Exception?
    IMO überflüssig.



  • TyRoXx schrieb:

    Hast du schon das in Betracht gezogen?

    template <class T>
    bool tryPop(T &value);
    

    Ja, Problem ist hier nur, dass man im Vorfeld ein (teures) Objekt erstellen muss. Eventuell sind auch Parameter gefordert, welche nicht vorhanden sind.

    TyRoXx schrieb:

    Die Variante mit dem unique_ptr blockiert mit dem unnötigen new den Stack relativ lange. Wenn es unbedingt unique_ptr sein muss, könnte man das Element erst bewegen, den Mutex wieder freigeben und dann new bemühen.

    Interssanter Einwand, danke, aber dann ist pop() nicht mehr Exception-save. Ich hole das Element vom Stack und gebe den Mutex frei, anschließend wirft new eine Exception und nun? 😉 Das Element ist nicht mehr auf dem Stack aber der Aufrufer von pop() hat es auch noch nicht.

    Insgesamt daher eher ein Grund sparsam eigene Exceptions zu werfen.



  • dot schrieb:

    Nö, ich mein eigentlich das: http://msdn.microsoft.com/en-us/library/a4xbdz1e.aspx
    Damit kann beispielsweise jeder Entwickler des Teams an bekannten Orten (z.B. MSBuild Extensions Directory) Property Sheets für alle möglichen Versionen aller möglichen Libs und SDKs die er so installiert hat ablegen.
    Ein VC++ Projekt verweist dann einfach auf die entsprechenden .props Dateien der benötigten libs und fertig. Damit kann jeder Entwickler seine Dateien organisieren wie er will und auch 100 verschiedene Versionen aller möglichen libs halten und trotzdem funktioniert jedes Projekt einfach so out of the box. Da muss ich dann weder irgendwelchen Code irgendwohin kopieren noch irgendwelche libs irgendwo eintragen. Und nur weil Visual Studio selbstverständlich eine GUI zum Editieren von Propery Sheets bietet, heißt das noch lange nicht, dass ich auf die angewiesen bin. Die GUI ist doch nur ein bequemes Interface zum Buildsystem.
    Mit deiner Zeile Code wär das imo überhaupt nicht besser gelöst, denn das pragma ist plattform-/compilerspezifisch und kommt mit verschiedenen Versionen, Suchpfaden, etc. rein prinzipiell schon nicht klar. Sowas gehört eben einfach nicht in den Code, genau für sowas gibts doch überhaupt erst ein Buildsystem...

    Und ich habe das Gefühl, daß die Property Sheets genau gar nichts von dem lösen, was mich interessiert.
    Das Argument "Sowas gehört nicht dahin" ist zwar traditionell, aber nicht stark. Verscjiedene lib-Versionen sind auch nicht mein Problem.

    Am Ende ist es wohl so, daß wir andere große Ärgerlichkeiten in Projekten hatten und jeweils Auswege für diese Ärgerlichkeiten gefunden haben und zum persönlichen Stil gemacht haben. Ohne, daß der andere Stil jetzt per se schlechter wäre.



  • 314159265358979 schrieb:

    weil die Syntax so unglaublich umständlich und hässlich ist.

    Umständlicher und hässlicher als

    result = callSomeFunction(useful_arg, that_damn_error_code);
    if (that_damn_error_code != SOME_MAGIC_NUMBER_INDICATING_ALL_GOOD)
    {
      wtf(lookup(that_damn_error_code));
    }
    

    nach diversen Funktionsaufrufen? Ich weiß ja nicht...



  • try
    {
        gimme_that_from_config;
    
        try
        {
            do_that_with_the_value;
        }
    
        catch(omg_no_workz)
        {
            cout << "shit happens\n";
        }
    }
    
    catch(what_was_the_name_of_that_error_that_indicates_that_the_value_doesnt_exist_in_the_config_file)
    {
        cout << "you are wasting my time\n";
    }
    

  • Administrator

    @Pi,

    try
    {
      foo();
      bar();
    }
    catch(ExceptionA)
    {
      // ...
    }
    catch(ExceptionB)
    {
      // ...
    }
    

    Grüssli



  • Denk dir halt nach dem inneren catch noch was dazu.



  • 314159265358979 schrieb:

    Denk dir halt nach dem inneren catch noch was dazu.





  • Oder man schaut einfach mal bei Lisp nach wie man es richtig macht: http://www.gigamonkeys.com/book/beyond-exception-handling-conditions-and-restarts.html



  • niemand schrieb:

    vorschlag schrieb:

    Verlinkt doch mal ein Open Source C++ Projekt, dass eurer Meinung nach Exceptions effektiv verwendet.

    http://paludis.pioto.org/

    Da schau ich nur 2 Dateien an und finde in der 2ten eine Methode die ewig viele Parameter hat, fast 200 Zeilen lang ist und folgendes enthält.

    291             catch (const Exception & e)
     292             {
     293                 std::cerr << "When processing '" << *q << "' got exception '" << e.message() << "' (" << e.what() << ")" << std::endl;
     294                 retcode |= 1;
     295             }
    

    Fail!
    http://git.pioto.org/gitweb?p=paludis.git;a=blob;f=src/clients/cave/cmd_find_candidates.cc;h=21db9b8e477a230a6ea6b236a26080fc79ab95a9;hb=HEAD


  • Mod

    vorschlag schrieb:

    niemand schrieb:

    vorschlag schrieb:

    Verlinkt doch mal ein Open Source C++ Projekt, dass eurer Meinung nach Exceptions effektiv verwendet.

    http://paludis.pioto.org/

    Da schau ich nur 2 Dateien an und finde in der 2ten eine Methode die ewig viele Parameter hat, fast 200 Zeilen lang ist und folgendes enthält.

    291             catch (const Exception & e)
     292             {
     293                 std::cerr << "When processing '" << *q << "' got exception '" << e.message() << "' (" << e.what() << ")" << std::endl;
     294                 retcode |= 1;
     295             }
    

    Fail!
    http://git.pioto.org/gitweb?p=paludis.git;a=blob;f=src/clients/cave/cmd_find_candidates.cc;h=21db9b8e477a230a6ea6b236a26080fc79ab95a9;hb=HEAD

    Erklärung?


Anmelden zum Antworten