boost exception handling



  • Hallo,

    ich benutze gerade zum 1. Mal boost filesystem und es gibt da eine Sache, die mir nicht ganz klar ist. Nehmen wir mal folgende Funktion:

    bool exists(const path& p);
    bool exists(const path& p, system::error_code& ec);
    
    Returns: exists(status(p)) or exists(status(p, ec)), respectively.
    
    Throws: filesystem_error; overload with error_code& throws nothing.
    

    So wie ich das verstehe heisst das: Die 1. Ueberladung wirft sofort eine Exception, wenn was schief geht und die 2. Ueberladung wirft im Fehlerfall gar keine Exception, sondern gibt den Fehlerfall im 2. Parameter ec zurueck. Stimmt das?

    Wenn die Funktionen Fehler ueber Exception/Parameter zurueckliefern, wieso hat sie dann ueberhaupt noch einen bool Rueckgabewert? 😕



  • ... weil bool nur zwei Fälle kennt: Existiert oder existiert nicht. Ein Fehler (z.B. beim lesen im Dateisystem) ist der dritte Fall.



  • MadridBezwinger schrieb:

    So wie ich das verstehe heisst das: Die 1. Ueberladung wirft sofort eine Exception, wenn was schief geht und die 2. Ueberladung wirft im Fehlerfall gar keine Exception, sondern gibt den Fehlerfall im 2. Parameter ec zurueck. Stimmt das?

    Genauso ist es.

    MadridBezwinger schrieb:

    Wenn die Funktionen Fehler ueber Exception/Parameter zurueckliefern, wieso hat sie dann ueberhaupt noch einen bool Rueckgabewert? 😕

    Nicht vorhanden ist für diese Funktion afaik kein Fehlerfall. Die Exception fliegt unter anderen Umständen.



  • XSpille schrieb:

    MadridBezwinger schrieb:

    Wenn die Funktionen Fehler ueber Exception/Parameter zurueckliefern, wieso hat sie dann ueberhaupt noch einen bool Rueckgabewert? 😕

    Nicht vorhanden ist für diese Funktion afaik kein Fehlerfall. Die Exception fliegt unter anderen Umständen.

    So sieht die status-Überladung, die in Version 1 genutzt wird, aus:

    system::error_code ec;
    file_status result = status(p, ec);
    if (result == status_error)
      throw filesystem_error(implementation-supplied-message, p, ec);
    return result;
    

    Also wenn die andere Überladung als file_status status_error liefert, wirft er, aber bei file_not_found und type_unknown nicht. (wenn ich es richtig verstanden habe).



  • Dh ein typischer Aufruf wird so aussehen?

    try{
    
       if(!exists(myPath)) {
          cout << "path does not exist";
            ...
        }
    catch(boost::filesystem::filesystem_error e) {
       cout << e.what();
    }
    

    Passt das so?



  • try{
    
       if(!exists(myPath)) {
          cout << "path does not exist";
            ...
        }
    catch(const boost::filesystem::filesystem_error& e) {
       cout << e.what();
    }
    

    😃



  • Ein typischer Aufruf wird so aussehen:

    if(!exists(myPath))
      ...
    

    Es ist doch erst die Idee von Exceptions, dass eine Exception eben nicht lokal behandelt werden muss, sondern dort behandelt werden kann, wo es Sinn macht. Alles in try/catch Blöcke zu wrappen geht völlig am Sinn von Exceptions vorbei...



  • dot schrieb:

    Es ist doch erst die Idee von Exceptions, dass eine Exception eben nicht lokal behandelt werden muss, sondern dort behandelt werden kann, wo es Sinn macht. Alles in try/catch Blöcke zu wrappen geht völlig am Sinn von Exceptions vorbei...

    👍

    Wichtigster Post im ganzen Thread!



  • dot schrieb:

    Ein typischer Aufruf wird so aussehen:

    if(!exists(myPath))
      ...
    

    Es ist doch erst die Idee von Exceptions, dass eine Exception eben nicht lokal behandelt werden muss, sondern dort behandelt werden kann, wo es Sinn macht. Alles in try/catch Blöcke zu wrappen geht völlig am Sinn von Exceptions vorbei...

    Der Code steht in main(). Ergo macht es hier Sinn es sofort in try Bloecke zu stecken...



  • MadridBezwinger schrieb:

    Der Code steht in main(). Ergo macht es hier Sinn es sofort in try Bloecke zu stecken...

    Nein.

    Es macht uU Sinn die gesamte main in einen try-catch Block zu packen - aber ein

    try { if exists(...) {} } catch(...) {}
    

    macht keinen Sinn.

    In C++ hat man keine try/catch Blöcke. Die sind so selten, dass ich garnichtmal mehr weiß, wann ich den letzten Geschrieben habe. Ist sicher >6 Monate her.

    Also: alle 6 Monate einmal try schreiben ist OK. wenn man es öfters macht, hats irgendwo was.



  • Sorry, aber so eine Verallgemeinerung ist Quark.
    Wenn ich den try Block klein halte, kann ich eine ganz spezifische Fehlermeldung ausgeben. Mache ich einen riesiges "globales" try, kann ich am Ende nur eine nichtssagende generische Meldung ausgeben.
    Ausserdem macht es gar keinen Sinn, den try Block unnoetig lange zu machen und damit Code zu erfassen, der total unkritisch ist.



  • Die Idee wäre eigentlich, dass das geworfene Objekt die Information über den Kontext nach draußen trägt...



  • Die Funktionen werfen alle die selbe Exception. Eine individuelle Fehlerbehandlung waere also nicht moeglich, mit einem grossen try Block.



  • MadridBezwinger schrieb:

    Die Funktionen werfen alle die selbe Exception.

    Ich hab jetzt nicht nachgeschaut, aber das bezweifle ich mal stark...

    Falls du mit dem Wunder der Polymorphie noch nicht vertraut bist, hier ein Link, der für dich interessant sein dürfte: http://de.wikipedia.org/wiki/Polymorphie_(Programmierung) 😉



  • dot schrieb:

    MadridBezwinger schrieb:

    Die Funktionen werfen alle die selbe Exception.

    Ich hab jetzt nicht nachgeschaut, aber das bezweifle ich mal stark...

    Falls du mit dem Wunder der Polymorphie noch nicht vertraut bist, hier ein Link, der für dich interessant sein dürfte: http://de.wikipedia.org/wiki/Polymorphie_(Programmierung) 😉

    Arroganz und Unwissenheit sind eine ganz schlechte Kombination.



  • Shade Of Mine schrieb:

    MadridBezwinger schrieb:

    Der Code steht in main(). Ergo macht es hier Sinn es sofort in try Bloecke zu stecken...

    Nein.

    Es macht uU Sinn die gesamte main in einen try-catch Block zu packen - aber ein

    try { if exists(...) {} } catch(...) {}
    

    macht keinen Sinn.

    In C++ hat man keine try/catch Blöcke. Die sind so selten, dass ich garnichtmal mehr weiß, wann ich den letzten Geschrieben habe. Ist sicher >6 Monate her.

    Also: alle 6 Monate einmal try schreiben ist OK. wenn man es öfters macht, hats irgendwo was.

    Man schreibt genau da try wo es gebraucht wird. Wenn das Programm darauf reagieren soll, dass eine Aktion mit einer Ausnahme fehlschlägt, dann tut es das eben. Und zwar nicht in der main ..



  • MadridBezwinger schrieb:

    dot schrieb:

    MadridBezwinger schrieb:

    Die Funktionen werfen alle die selbe Exception.

    Ich hab jetzt nicht nachgeschaut, aber das bezweifle ich mal stark...

    Falls du mit dem Wunder der Polymorphie noch nicht vertraut bist, hier ein Link, der für dich interessant sein dürfte: http://de.wikipedia.org/wiki/Polymorphie_(Programmierung) 😉

    Arroganz und Unwissenheit sind eine ganz schlechte Kombination.

    Ein Blick in den Quellcode von boost verrät: Wie zu erwarten war, ist der von exists() im Fehlerfall geworfene boost::filesystem_error von boost::exception abgeleitet und liefert eine detailierte Beschreibung des genauen Fehlers inklusive diagnostischer Information wie z.B. Name der Funktion, Source File und Zeilennummer der genauen Stelle, wo die Exception geworfen wurde...



  • dot schrieb:

    MadridBezwinger schrieb:

    dot schrieb:

    MadridBezwinger schrieb:

    Die Funktionen werfen alle die selbe Exception.

    Ich hab jetzt nicht nachgeschaut, aber das bezweifle ich mal stark...

    Falls du mit dem Wunder der Polymorphie noch nicht vertraut bist, hier ein Link, der für dich interessant sein dürfte: http://de.wikipedia.org/wiki/Polymorphie_(Programmierung) 😉

    Arroganz und Unwissenheit sind eine ganz schlechte Kombination.

    Ein Blick in den Quellcode von boost verrät: Wie zu erwarten war, ist der von exists() im Fehlerfall geworfene boost::filesystem_error von boost::exception abgeleitet und liefert eine detailierte Beschreibung des genauen Fehlers inklusive diagnostischer Information wie z.B. Name der Funktion, Source File und Zeilennummer der genauen Stelle, wo die Exception geworfen wurde...

    Jo, die Exception fliegt aber in boost::filesystem::exists, reichlich uninteressant in welcher Datei/Zeile/Funktion da genau geworfen wird, bringt dem Nutzer reichlich wenig.

    try
    {
        ... Code ...
    
        std::string configFile = "...";
        std::string usersFile = "...";
        std::string pluginsFile = "...":
    
        ... Code ...
    
        if(exists(configFile))
            loadConfig(configFile);
    
        if(exists(usersFile))
            loadUsers(usersFile);
    
        if(exists(pluginsFile))
            loadPlugins(pluginsFile);
    }
    catch(filesystem_error const& e)
    {
        Na, bei welchem Ladevorgang gabs das Problem?
    }
    


  • Ethon schrieb:

    try
    {
        ... Code ...
    
        std::string configFile = "...";
        std::string usersFile = "...";
        std::string pluginsFile = "...":
    
        ... Code ...
    
        if(exists(configFile))
            loadConfig(configFile);
    
        if(exists(usersFile))
            loadUsers(usersFile);
    
        if(exists(pluginsFile))
            loadPlugins(pluginsFile);
    }
    catch(filesystem_error const& e)
    {
        Na, bei welchem Ladevorgang gabs das Problem?
    }
    

    Was soll das exists denn da?



  • Ethon schrieb:

    Na, bei welchem Ladevorgang gabs das Problem?

    Steht in der Exception.
    Ist aber für den catch Block irrelevant.


Log in to reply