[solved] Problems with reimplementing QApplication::notify for exception handling



  • In my Qt application I use external libraries that can throw exceptions (specifically ones derived from the std::exception type). I would like to handle them in a more general way than individually surrounding each library routine calls with a try-catch.

    When an exception is unhandled in a Qt application and causes it to terminate, the error message says that one should reimplement QApplication::notify to handle errors and so the documentation suggests this somewhere. So after I looked for some examples in the topic, I created my SafeApplication class that inherits QApplication and reimplemented its notify method like that:
    @
    bool SafeApplication::notify(QObject *receiver_, QEvent *event_)
    {
    try
    {
    return QApplication::notify(receiver_, event_);
    }
    catch (std::exception &ex)
    {
    std::cerr << "std::exception was caught" << std::endl;
    }

    return false;
    }
    @

    I used this class in my main.cpp like this:

    @
    int main (int argc, char **argv)
    {
    SafeApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
    }
    @

    The problem is:

    • if I build my application in release mode, everything goes fine, that is if I throw an exception somewhere and does not handle it, I get the message I expect,
    • but if I build in debug mode (which I usually use while developing, of course), the application crashes with a SIGSEGV immediately after starting, before any exception was thrown. According to the debugger the crash occurs in a.exec() (so not before it, also some events seem to go through notify before a.exec()... this is also strange for be becouse I thought that exec is responsibel for starting the main event loop).

    Its irrelevant that which Qt version I use, I tried it with 4.7.4, 4.8.0 and 4.8.1 and all is the same. I can imagine that this problem is platform-dependent, so my configuration is: XUbuntu 12.04 64-bit desktop edition, with all suggested patches installed, gcc/g++ 4.6 and the latest Qt SDK installed with the "wizard" installer.

    Do I something wrong or can anyone suggest a better way or workaround or any idei for that problem?

    Thanks for the help in advance.

    winnetou



  • I (one of my colleagues, to be precise) solved the problem after quite a long time. While the solution is so simple I could not absolutely figure out why was that on some machines my old code worked and on some others not, and why did it produce the specific behaviour that it had.

    So, after this introduction, I will explain the solution.

    My old reimplementation of QApplication's constructor (the one that made my application crash with a SIGBUS or SIGSEGV immediately after startup) had this signature:
    @SafeApplication::SafeApplication(int argc, char *argv[]);@

    The correct signature (with which everything works fine) is the one you can find in the docs for QApplication, namely:
    @SafeApplication::SafeApplication(int &argc, char *argv[]);@

    Notice that the only difference between the two signatures is the reference symbol (&) for the first argument.

    My idea about why makes it worth to put or not put the reference symbol is, that QApplication processes the command line arguments and remove some of them in its constructor, so it should modify argc (count of arguments). So that, if I pass argc by value, modifications are local to the constructor, but it still can change the value of argv (the argument list) globally.
    This explanation is not the best and, I think, is not the real one. It's just my only idea. But the first thing that talks against it is that if I have started my program without any command line arguments (i.e. QApplication could not remove any arguments), the crash still occured exactly the same way.

    So please write a post here and let me know if you have a better explanation then mine! Thanks!



  • YOU ARE A FRIGGING GENIUS.

    I spent two goddamn years inserting this disgusting crutch to each and every of my projects:

    @CONFIG(debug, debug|release) {
    CONFIG += use_native_qapp
    message(Using native QApplication)
    } else {
    message(Using QSingleApplication)
    }

    !CONFIG(use_native_qapp):include(../qt-solutions-qt-solutions/qtsingleapplication/src/qtsingleapplication.pri)

    CONFIG(use_native_qapp):DEFINES +=
    USE_NATIVE_QAPPLICATION@

    @#ifdef USE_NATIVE_QAPPLICATION
    QApplication app(argc, argv);
    #else
    SingleAppWithExceptHandling app(argc, argv);
    #endif@

    And now I FINALLY can forget about this. GOOD GOD.
    I can't even describe how grateful I am.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.