std::runtime_error wird nicht gefangen



  • Das funktioniert wie erwartet

    #include <fstream>
    #include <string>
    #include <stdexcept>
    #include <iostream>
    
    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    {
        std::string buf, line;
        std::ifstream in(file_name.c_str(), std::ios_base::in);
        if(!in.is_open())
        {
            throw std::runtime_error(file_name);
        }
        while(std::getline(in,line))
            buf += line;
        return buf;
    }
    
    class Foo {
    public:
        Foo(const std::string& filename)
        {
            std::string bar;
            try {
                bar = loadFile(filename);
            } catch(std::runtime_error& ex) {
                std::cerr << ex.what() << " konnte nicht geöffnet werden";
                mem = 0;
                return;
            }
            mem = 1;
        }
    private:
        int mem;
    };
    
    class Other {
    public:
        Other():member("blub"){}
    private:
        Foo member;
    };
    
    int main(int argc, char *argv[])
    {
        Other o;
        0;
    }
    

    Problem ist, wenn ich genau diesen Code

    try {
                bar = loadFile(filename);
            } catch(std::runtime_error& ex) {
                std::cerr << ex.what() << " konnte nicht geöffnet werden";
                mem = 0;
                return;
            }
    

    in meine Software paste, kommts zum abort().

    Das kann ja eigentlich nur heißen, das zwei Excpetions fliegen, von denen ich nur eine gefangen kriege. Wenn ich catch(...) mache, ist das Ergebnis aber das gleiche.

    Irgendwie steh ich gerade voll auf dem Schlauch.

    Philipp



  • Mal eine andere Frage, bist du dir sicher, dass is_open() an der Stelle die richtige Methode ist? Das eine zweite Exception fliegt ist unwahrscheinlich, wenn du sie nicht fangen kannst. Vielleicht darfst du is_open() nur auf eine vorhandene Datei anwenden?

    http://www.cplusplus.com/reference/iostream/ifstream/ifstream/
    Dritter Absatz der Beschreibung.



  • Exception-Spezifikationen sind deprecated, weg damit! 🤡



  • Okay, diese zwei Funktionen gibts:

    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    {
        std::string buf;
        std::string line;
        std::ifstream in(file_name.c_str(), std::ios_base::in);
        if(!in.is_open())
        {
            throw std::runtime_error(file_name);
        }
        while(std::getline(in,line))
            buf += line;
        return buf;
    }
    
    void foo() throw (std::runtime_error)
    {
        throw std::runtime_error("foo");
    }
    

    Folgendes passiert:

    try {
            //config = loadFile(config_file_name);  // abort -> in der abort-Meldung steht der korrekte File-name
            foo();  // Exception wird korrekt gefangen
        } catch (std::runtime_error& ex){
            Log() << Log::Fail << "Could not open " << ex.what() << ". SCS does not work without this file." << Log::endl;
            return;
        }
    

    Das heißt, aus loadFile() muss mehr als eine Exception kommen.



  • In der main hast du kein return drin
    In der ursprünglichen loadFile auch nicht...

    Ich vermute mal, dass deine Exception gefangen wird, aber der
    Stream nicht geflusht wird.

    std::cerr << ex.what() << " konnte nicht geöffnet werden" << std::endl;
    


  • kuck mal, ob 'irgendetwas' gefangen wird...

    } catch(...){
    
    }
    

    danach würde ich dann const std::exception& versuchen zu fangen



  • XSpille schrieb:

    In der main hast du kein return drin

    Stimmt. Da funktioniert aber auch alles

    Ich vermute mal, dass deine Exception gefangen wird, aber der
    Stream nicht geflusht wird.

    Das logfile wird aber geflusht.
    Außerdem, selbst wenn der stream nicht geflusht würde, dürfte ja kein abort() kommen.



  • XSpille schrieb:

    kuck mal, ob 'irgendetwas' gefangen wird...

    } catch(...){
    
    }
    

    danach würde ich dann const std::exception& versuchen zu fangen

    Habe ich gerade probiert. auch die ellipse catcht nix.



  • XSpille schrieb:

    Ich vermute mal, dass deine Exception gefangen wird, aber der
    Stream nicht geflusht wird.

    std::cerr << ex.what() << " konnte nicht geöffnet werden" << std::endl;
    

    Ein std::endl bewirkt ein std::flush und ein '\n'.



  • tjatja schrieb:

    XSpille schrieb:

    Ich vermute mal, dass deine Exception gefangen wird, aber der
    Stream nicht geflusht wird.

    std::cerr << ex.what() << " konnte nicht geöffnet werden" << std::endl;
    

    Ein std::endl bewirkt ein std::flush und ein '\n'.

    Danke für die Info, allerdings ist mir das klar...
    Ein Zeilenumbruch nach einer Meldung kann auch nichts schaden 😉



  • Den Hinweis auf fail() zu checken hast du gesehen?

    if (in.fail() || !in.is_open())
        throw bla;
    


  • okay, habe den Fehler weiter eingegrenzt

    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    {
        std::string buf, line;
        std::ifstream in(file_name.c_str(), std::ios_base::in);
        if(!in)
        {
            throw std::runtime_error(file_name);
        }
        return "";   // das funktioniert
    
        while(std::getline(in,line))
            buf += line;
        return buf;
    }
    

    Man beachte, das die Funktion in jedem Fall einen leeren String zurückgibt.

    Das Verhalten ist das erwartete: Für eine existente Datei gibt sie einen leeren String zurück, für eine nicht existente Datei kommt eine Exception, die auch gefangen wird.

    Entferne ich das

    return "";
    

    wird abort() aufgerufen im Falle einer nicht existenten Datei.



  • EDIT: ups... Falsche Vermutung



  • So geht's:

    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    {
        std::string buf, line;
        std::ifstream in(file_name.c_str(), std::ios_base::in);
        if(in.fail() || !in)
        {
            throw std::runtime_error(file_name);
            return "";
        } else {
            while(std::getline(in,line))
                buf += line;
            return buf;
        }
    }
    

    Kann mir vielleicht einer erklären, wo hier das Problem war?
    Ich hab nämlich keinen Schimmer, warum es jetzt geht.

    Philipp



  • Was ist denn mit dem Forum los? Jeder schreibt hier "mach mal catch(...)" aber das kann doch nicht funktionieren wenn die Funktion spezifiziert hat, was sie werfen darf..

    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    

    Da spezifizierst du, dass du nur runtime_error werfen darfst. Wenn eine andere Exception kommt, wird terminiert. Da bringt dir dein catch(...) auch nix mehr. Mach das mal weg und guck DANN mit catch(...) was eigentlich geworfen wird.



  • NewSoftzzz schrieb:

    Was ist denn mit dem Forum los? Jeder schreibt hier "mach mal catch(...)" aber das kann doch nicht funktionieren wenn die Funktion spezifiziert hat, was sie werfen darf..

    std::string loadFile(const std::string& file_name) throw(std::runtime_error)
    

    Da spezifizierst du, dass du nur runtime_error werfen darfst. Wenn eine andere Exception kommt, wird terminiert. Da bringt dir dein catch(...) auch nix mehr. Mach das mal weg und guck DANN mit catch(...) was eigentlich geworfen wird.

    Bekenne mich schuldig.
    Ich verwende nie throw und war der Meinung, dass sonst eine std::bad_exception
    zurückkommt. Die ist allerdings (scheinbar) nur der Fall, wenn throw diese
    auch enthält.



  • tja schrieb:

    Exception-Spezifikationen sind deprecated, weg damit! 🤡

    Der Beitrag ging verloren.



  • tja schrieb:

    Exception-Spezifikationen sind deprecated, weg damit! 🤡

    Stimmt, er hat im Prinzip das gleiche gesagt wie ich. Aber wenn man wie ein Troll schreibt wird man halt nicht ernst genommen 😞

    mfg, René~



  • NewSoftzzz schrieb:

    tja schrieb:

    Exception-Spezifikationen sind deprecated, weg damit! 🤡

    Stimmt, er hat im Prinzip das gleiche gesagt wie ich. Aber wenn man wie ein Troll schreibt wird man halt nicht ernst genommen 😞

    mfg, René~

    Du meinst also, wenn man ein Clown-Smiley benutzt, dass man damit kennzeichnet ein Troll zu sein?
    Dann sollte Marcus++ das Smiley löschen!
    🤡

    XSpille schrieb:

    Danke für die Info, allerdings ist mir das klar...

    Ist klar...



  • Wer in C++ Exception-Spezifikationen verwendet, ist selbst schuld. Es hat schon seinen Grund, wieso sie in C++0x deprecated sind.

    Siehe auch http://www.gotw.ca/publications/mill22.htm


Anmelden zum Antworten