Qt/C++ Error handling

后端 未结 5 1916
谎友^
谎友^ 2020-12-12 17:14

I\'ve been doing a lot of research about handling errors with Qt/C++ and I\'m still as lost as when I started. Maybe I\'m looking for an easy way out (like other languages p

相关标签:
5条回答
  • 2020-12-12 17:26

    Override QCoreApplication::notify() and add try-catch there. That, and something in main() covers most cases in my experience.

    Here's sort-of how I do it. Note that I'm using C++ RTTI here, not Qt's version, but that's just for convenience in our apps. Also, we put up a QMessageBox with the info and a link to our log-file. You should expand according to your own needs.

    bool QMyApplication::notify(QObject* receiver, QEvent* even)
    {
        try {
            return QApplication::notify(receiver, event);
        } catch (std::exception &e) {
            qFatal("Error %s sending event %s to object %s (%s)", 
                e.what(), typeid(*event).name(), qPrintable(receiver->objectName()),
                typeid(*receiver).name());
        } catch (...) {
            qFatal("Error <unknown> sending event %s to object %s (%s)", 
                typeid(*event).name(), qPrintable(receiver->objectName()),
                typeid(*receiver).name());
        }        
    
        // qFatal aborts, so this isn't really necessary
        // but you might continue if you use a different logging lib
        return false;
    }
    

    In addition we use the __try, __except on Windows to catch asyncronous exceptions (access violations). Google Breakpad could probably serve as a cross-platform substitute for that.

    0 讨论(0)
  • 2020-12-12 17:28

    Qt doesn't generally use, or entirely support exception throwing (if you can belive that!)

    Check out these links:

    Why doesn't Qt use exception handling?

    http://doc.qt.io/qt-5/exceptionsafety.html

    That said, the answers from @Crazy Eddie and @Macke are pretty good, but don't always work. In particular, I found you can't use either of them from a slot function you've invoked from QML. So, I created a hacky work around for this problem. *Use this in conjunction with theirs - not in place of it.

    First, I created class derived from QException, which I'll skip over here, but is something you'll probably want to do. In this post, I just refer to it as "MyQException".

    Anyway, add this header for a class called QmlSlotThrower:

    #ifndef QMLSLOTTHROWER_H
    #define QMLSLOTTHROWER_H
    
    #include "MyQException.h"
    
    class QmlSlotThrower
    {
    public:
        static QmlSlotThrower *get()
        {
            static QmlSlotThrower instance;
            return &instance;
        }
        QmlSlotThrower( QmlSlotThrower const& ) = delete;
        void operator=( QmlSlotThrower const& ) = delete;
    
        void throwToTop( const MyQException &exception );
    
    private:
        QmlSlotThrower(){}
    };
    static QmlSlotThrower *qmlSlotThrower = QmlSlotThrower::get();
    
    #define throwFromQmlSlot( exc ) qmlSlotThrower->throwToTop( exc ); return;
    
    #endif // QMLSLOTTHROWER_H
    

    Then, it's cpp:

    #include "QmlSlotThrower.h"
    #include <QTimer>
    
    class AsynchronousThrower: public QObject
    {
    Q_OBJECT
    public:
        void throwThis( const MyQException &exception )
        {
            exception_ = exception;
            QTimer::singleShot( 0, this, SLOT( throwIt() ) );
        }
    private slots:
        void throwIt(){ throw exception_; }
    private:
        MyQException exception_;
    };
    static AsynchronousThrower asycnThrower;
    
    // This is needed to allow the Q_OBJECT macro
    // to work in the private classes
    #include "QmlSlotThrower.moc"
    
    // --------------------------------
    
    void QmlSlotThrower::throwToTop( const MyQException &exception )
    { asycnThrower.throwThis( exception ); }
    

    Finally, here's an example implementation:

    void someQMLSlot()
    {
        // Qt has been progressively adding exception handling
        // support, but you still cannot throw from a QML
        // triggered slot. It causes an uncatchable fatal error!
    
        // As a general rule, don't throw in Qt unless you are
        // certain something is there to catch it.  You cannot
        // count on an uncaught exception handler at a top level
        // to always work.  This QML problem is a perfect example.
    
        // So this is not an option here!
        //throw MyQException( "Something terrible occured!" );
    
        // This work around, however, can be used instead!
        //throwFromQmlSlot( MyQException( "Something terrible occured!" ) )
    
        // Or, to be more robust in illustrating how you can still use
        // normal throws from nested functions even, you can do this:
        try{ throw MyQException( "Something terrible occured!" ); }
        catch( const MyQException &e) { throwFromQmlSlot( e ) }
    
        qDebug() << "YOU SHOULD NEVER SEE THIS!!";
    }
    

    ONLY USE THE MACRO DIRECTLY FROM YOUR SLOT!

    0 讨论(0)
  • 2020-12-12 17:33

    You can put a catch (...) in or around main() Here's around:

    int main() try
    {
      ...
    }
    catch (std::exception & e)
    {
      // do something with what...
    }
    catch (...)
    {
      // someone threw something undecypherable
    }
    
    0 讨论(0)
  • 2020-12-12 17:34

    I prefer error handling using exceptions. Please find the below sample code:

    ErrorStatus ExplodeToLine()
    {
        var errorStatus = new ErrorStatus();
    
        try
        {
            errorStatus = fun();
    
            if (!errorStatus.ok())
            {
                throw new VicException(L"fun failed");
            }
    
    
            errorStatus = fun1();
    
            if (!errorStatus.ok())
            {
                throw new VicException(L"fun1 failed");
            }
    
    
            errorStatus = fun2();
    
            if (!errorStatus.ok())
            {
                throw new VicException(L"fun2 failed");
            }
    
            errorStatus.setError(ErrorType.OK);
        }
        catch (VicException vicExp)
        {
            Log(vicExp.errorMsg());
        }
        catch (Exception exp)
        {
            Log(exp.errorMsg());
        }
    
        return error_status;
    }
    
    0 讨论(0)
  • 2020-12-12 17:36

    Google Breakpad is a cross-platform application error reporting framework. Maybe it helps?

    (I haven't tried it in our c++/qt apps yet, but I'd love to get around to it someday...)

    0 讨论(0)
提交回复
热议问题