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

[solved] console application does not exit



  • I have created a console application from the QtCreator wizard. I then wrote this simple code:

    #include <QCoreApplication>
    #include <iostream>
    using namespace std;
    
    int main(int argc, char *argv[]){
     QCoreApplication app(argc, argv);
    
     int number;
     cout << "insert any number: ";
     cin >> number;
     cout << "the application should now exit with return code: " << number << endl;
     app.exit(number);
    
     int retcode = app.exec();
    
     cout << "Although the app.exit() function has been called" << endl;
     cout << "this message will never get outputted in the console" << endl;
     cout << "just like app.exec() is not returning" << endl;
    
     return retcode;
    }
    

    For some reason though, the application won't exit at all. When calling app.exit(number) nothing happens... the application just keeps the console window opened, but it doesn't get further in the code. As you can read in the code, the last 3 cout lines should be outputted as soon as app.exec() returns (which means, as soon as I call app.exit(number) ), but instead nothing happens.
    The only way to get the console window closed is to press CTRL + C (it will show a "PRESS ANY KEY TO CONTINUE..." message, and then it would exit) or to manually closing the window from the titlebar X button.

    Can someone tell what am I doing wrong?


  • Moderators

    You call exit before the event loop is even started so it does nothing. Then an event loop is started and nothing calls exit from within it so it just keeps going.

    This is one way to do it:

    // runner.h
    #include <QObject>
    class Runner : public QObject {
        Q_OBJECT
    public slots:
        void run() ;
    };
    
    //main.cpp
    #include <QCoreApplication>
    #include <QTimer>
    #include "runner.h"
    
    int main(int argc, char *argv[]) {
        QCoreApplication a(argc, argv);
    
        Runner r;
        QTimer::singleShot(0, &r, SLOT(run()));
    
        return a.exec();
    }
    
    void Runner::run() {
        //do stuff
        QCoreApplication::exit(0);
    }
    

    This will call run() from within the event loop. run() then calls exit() which ends loop.

    Or, if you're not actually using the event loop(for connections, timers etc.) don't call a.exec() at all, just return number; and be done with it.



  • Let me get this right.
    When I call app.exec() I start an event loop. May I ask then what code will actually be running in the event loop? Any code between the QCoreApplication declaration and the event loop start ( app.exec() ) ?

    Also, your code above seems to be as good as mine since you are just creating an object from the class Runner, you're doing some stuff, and then you're calling the QCoreApplication::exit(0) method - I do the same thing, just, I am not starting a timer or other stuff; I'm directly outputting some strings with cout and then call app.exit(0). Still, your code works, mine doesn't. So what's the difference from my code to your code? Is it that QTimer?



  • Hiii T3STY,

    This is a very simple logic to understand ..if you put exit() or quit() before the exec() then it is meaningless .
    and if you put exit() or quit() after exec() then it is meaningless too because the functions exit() or quit() will not be invoked due to event loop (started by exec() the control will not be reached out there.
    So one solution is use the timer as Chris has given you, so that quit() and exit() functions could be executed.
    I hope it will clear your doubt.


  • Moderators

    The exec() runs in a loop and executes any pending events, connections, signals, delayed deletions etc. It doesn't run the code between QCoreApplication declaration and exec() invocation. How could it know what's there? There's no such facility in c++.

    In your code there's nothing to do in the exec() loop since you do all the work before it even starts. This goes also for your exit() call. It returns immediately and since it's not called in a loop it basically is a no-op.

    Now in my code I call a timer single-shot with 0 delay, which basically puts a timer event on a stack. This does not run the run() method yet. Now I call exec() which starts the loop. The loop gets that stored event off the stack and runs run(). run() in turn calls exit(). This exit() is inside a loop so it signals it to finish.


  • Moderators

    Oh, and the only reason I use a class with a slot is because QTimer was not yet updated to use the new c++11 connection syntax and lambdas like the rest of Qt. What I would much more like to do is something like this:

    int main(int argc, char *argv[]) {
        QCoreApplication a(argc, argv);
    
        QTimer::singleShot(0,[](){
             //do stuff
             QCoreApplication::exit(0);
        });
        return a.exec();
    }
    

    But that's not in Qt right now, although I sincerely hope someone takes a look at QTimer soon.



  • So, after all, it was that QTimer the difference... now it looks much clearer to me how this event loop works. Thank you very much!


Log in to reply