Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Why std::exception make QCoreApplication::exec() avoid terminating the application?



  • Hello,

    I try to implement my exception class which inherent from std::exception but after throwing an instance of my custom exception the QCoreApplication::exec never return and the app got stuck in an infinite loop. I couldn't find the reason.

    To clarify the case please have a look at the code:
    customexception.h

    #ifndef CUSTOMEXCEPTION_H
    #define CUSTOMEXCEPTION_H
    
    #include <string.h>
    #include <iostream>
    using namespace std;
    
    
    class IOException : public std::exception
    {
    protected:
        string m_msg;
    public:
        IOException():m_msg("") {}
        virtual ~IOException(){}
    };
    /******************************************************************************/
    class FileNotFoundException : public IOException
    {
    public:
        FileNotFoundException()
        {
            m_msg = "File Not Found!";
        }
        FileNotFoundException(const string &path)
        {
            m_msg = "File \"" + path + "\" Not Found!";
        }
        ~FileNotFoundException(){}
    
    
        // exception interface
    public:
        virtual const char *what() const noexcept override
        {
                    return m_msg.c_str();
        }
    };
    
    #endif // CUSTOMEEXCEPTION_H`
    

    In this class as you can see FileNotFoundException inherent from IOException which is derived from std::exception and the main.cpp is like below:

    int main(int argc,char *argv[])
    {
        QCoreApplication a(argc,argv);
        cout << "Start ..." << endl;
    
        try
        {
            throw FileNotFoundException("testfile");
        } catch (std::exception &exc)
        {
            cout << exc.what() << endl;
        }
        return a.exec();
    }
    

    the application never return.
    However, if I change return a.exec(); with return 0; the application return immediately.
    Also, if I change the FileNotFoundException to inherent from std::exception instead of IOException and change chatch statment to catch (IOException &exc) in main.cpp things are going to work properly and return a.exec(); will return without any trouble.

    I would appreciate if someone has an explanation for that.



  • @Alien
    I don't have Qt atm, it's in my head.

    You only catch (IOException, so I would expect different behaviour.

    With public IOException I would expect code to catch, print your own message, continue, and require you to "stop" the execution.

    With public std::exception I would expect code to not catch, exit, print terminate ... Press <RETURN>.

    Do you find any different?

    If you had catch (std::exception instead I would expect both class declarations to be caught like the first case above.


  • Lifetime Qt Champion

    You call QCoreApplication::exec() which starts an eventloop which you never quit so what do you expect?



  • Dear @Christian-Ehrlicher ,
    Thanks for your reply; let me show you the output:

    Start ...
    terminate called after throwing an instance of 'FileNotFoundException'
      what():  File "testfile" Not Found!
    Press <RETURN> to close this window...
    

    This is the output that I expect. The app terminate normally, but the below output is what I don't expect:

    Start ...
    File "testfile" Not Found!
    

    It is waiting and not terminate by itself. I have to click on stop button (the red squared button) to close the application.


  • Lifetime Qt Champion

    @Alien said in Why std::exception make QCoreApplication::exec() avoid terminating the application?:

    I have to click on stop button (the red squared button) to close the application.

    Correct - you catch the exception and then start the Qt eventloop as I already told you.



  • @Christian-Ehrlicher
    @Allen is talking about more complex, strange behaviour.

    From my reading, he is claiming, in the test code he shows, that which exception type he throws and catches successfully before he reaches the return a.exec(); affects how that actually then behaves? Sometimes it does not return, sometimes it returns immediately. Which sounds odd, if it's really the case....


  • Lifetime Qt Champion

    IOException is derived from std::exception so it is catched. Then the eventloop is started and the program runs - where's the problem?



  • @Christian-Ehrlicher
    I misunderstood his output.

    @Alien
    When your exception is not caught you get the "terminate" message, and the program exits without running the a.exec(). You get the Press <RETURN> to close this window....

    When your exception is caught, it prints your error message, and continues to the a.exec(). That means you will have to stop the program, like clicking that button. Your expectation that QCoreApplication::exec() should "exit/terminate immediately" is wrong. It is running an event loop. This has nothing to do with whether you previously caught an exception.



  • Dear @Christian-Ehrlicher and @JonB I expect the same behaviour when one exception occurs. Please have a look at my main.cpp in this code I deliberately throw an exception so I expect the same behaviour. The thing I cannot understand is why the output is different :

    Start ...
    terminate called after throwing an instance of 'FileNotFoundException'
      what():  File "testfile" Not Found!
    Press <RETURN> to close this window...
    

    in this output catch statement caught the exception and the application terminated but in the second output :

    Start ...
    File "testfile" Not Found!
    

    catch statement still works as we can see "File "testfile" Not Found!" but the application doesn't terminate?! Furthermore please examine at the output. Why one has " what():" and another doesn't have?



  • @Alien said in Why std::exception make QCoreApplication::exec() avoid terminating the application?:

    Why one have " what():" and another doesn't have?

    Just like I was, you are misunderstanding the output you are seeing!! That is the key :)

    Trust me: put a qDebug() << "In catch" as the first line inside your catch (... &exc). Now watch when you do versus do not see that line. You will not see it in the terminate ... what situation, that message is what the debugger must print when an exception is not caught. I was confused because it prints the result from exc.what() just like your handler does. Try changing your own message to be quite different and you'll see!



  • @JonB could you please check this code:

    main.cpp
    
    #include "customexception.h"
    #include <QCoreApplication>
    #include <QtDebug>
    
    int main(int argc,char *argv[])
    {
        QCoreApplication a(argc,argv);
        cout << "Start ..." << endl;
    
        try
        {
            throw FileNotFoundException("testfile");
        } catch (IOException &exc)
        {
            qDebug()<<"In catch ststement ";
            cout << exc.what() << endl;
        }
        qDebug()<<"Out of catch statement ";
        return a.exec();
    }
    
    

    and the header:

    customexception.h
    
    #ifndef CUSTOMEXCEPTION_H
    #define CUSTOMEXCEPTION_H
    
    #include <string.h>
    #include <iostream>
    using namespace std;
    
    
    class IOException : public std::exception
    {
    private:
        string m_msg;
    public:
        IOException():m_msg("") {}
        virtual ~IOException(){}
    };
    
    /******************************************************************************/
    class FileNotFoundException : public IOException
    {
    protected:
        string m_msg;
    public:
        FileNotFoundException()
        {
            m_msg = "File Not Found!";
        }
        FileNotFoundException(const string &path)
        {
            m_msg = "File \"" + path + "\" Not Found!";
        }
        ~FileNotFoundException(){}
    
    
        // exception interface
    public:
        virtual const char *what() const noexcept override
        {
                    return m_msg.c_str();
        }
    };
    
    #endif // CUSTOMEEXCEPTION_H
    
    

    Please change the "class FileNotFoundException : public IOException" with "class FileNotFoundException : public std::exception" and watch the output (don't modify the main.cpp)
    Do you believe is that normal?



  • @Alien
    I don't have Qt atm, it's in my head.

    You only catch (IOException, so I would expect different behaviour.

    With public IOException I would expect code to catch, print your own message, continue, and require you to "stop" the execution.

    With public std::exception I would expect code to not catch, exit, print terminate ... Press <RETURN>.

    Do you find any different?

    If you had catch (std::exception instead I would expect both class declarations to be caught like the first case above.



  • @Alien
    I have now had a chance to actually edit & run the code.

    It behaves exactly as I expected, in all cases I mentioned. If it does not match your expectations, I don't know what you are expecting!

    [EDIT Next stuff was spurious problem --- see comment at end.]

    On a completely separate matter. As I change between:

    class FileNotFoundException : public IOException  --> public std::exception
    

    or between

    catch (IOException &exc) --> catch (std::exception &exc)
    

    Qt Creator (using default clang code completion)/the build process goes absolutely doolally. Loads & loads of lines, in both files, become red-underlined as erroneous crazily, the build process reports in red hundreds of spurious "control" characters in the source code and never completes but hangs; I have to kill Creator from the command-line. Re-entering does not help; nor does cleaning or re-running qmake. I have to exit, delete all files in the build output directory, and re-enter. Only then does it come back to its senses....

    This is perfectly repeatable. It's pretty depressing. I have had trouble with needing to clean out the build directory before when I change certain things in header files, but never anywhere as bad as this. I use Qt/Creator/gcc as supplied with Ubuntu 20.04, plus clang 8. But I'm guessing there's no point start reporting this, as Qt 6 moves toward cmake maybe/hopefully this will all change and go away.

    But just to say: I don't know how you fared making these changes --- you might want want to do as I did and exit, clear out your build directory of all intermediate files, re-enter --- but once it compiles as it should the run-time behaviour is as I stated & expected.

    [EDIT With @Christian-Ehrlicher's kind help, I have discovered why the last 3 paragraphs above were happening to me. I named my project & executable exception. Perfectly reasonable, you might think.... But somewhere --- not in my code, probably in C++ std header file stuff being included to use std::exception? Yup, I see file exists /usr/include/c++/9/exception --- it must go something like #include <exception> (Yep, it does). Unbelievably: once my output build directory contains the executable exception file, both clang and the compilation must read that binary file in place of some exception header file, and that is what caused everything to go wrong, including it complaining about "control characters" (binary bytes) and generating 130 thousand errors in 10 minutes of compiling..... Qt insists on having your build-output directory on INCPATH/INCLUDEPATH, because of the files it generates like ui_....h & moc_..., which is disastrous. I am furious about this, the moral is you're supposed to know the names of every system header file which might get included and never name your executable the same as one of them, which is ridiculous C++/Qt :@ :@.


  • Lifetime Qt Champion

    @Alien said in Why std::exception make QCoreApplication::exec() avoid terminating the application?:

    Do you believe is that normal?

    Yes as I already explained two times (and @JonB also already more than once) - when FileNotFoundException derives from IOException the exception is catch by catch IOException, when it's derived form std::exception it is not catch - plain basic c++.



  • Dear @Christian-Ehrlicher , thanks. you are right


Log in to reply