Catch exceptions in QT/C++ (QGuiApplication) (override notify() method?)
-
How can I override
QGuiApplication::notify()
According to my research this appears to be the way to actually catch exceptions that arise in a QT/C++ application - described in several places, e.g. https://stackoverflow.com/a/14804711/1495940
However, any description of it or examples I can find speak only of overriding
QApplication::notify()
orQCoreApplication::notify()
, notQGuiApplication::nofity()
. (Even thoughQGuiApplication
inherits fromQCoreApplication
.When I try to do it, my (Linux embedded) application crashes when I initialise
QQuickView
.Here is what I have:
DebugApplication.h
#ifndef DEBUGAPPLICATION_H #define DEBUGAPPLICATION_H #include <QGuiApplication> #include <typeinfo> class DebugApplication : public QGuiApplication { public: DebugApplication(int argc, char* argv[]); bool notify(QObject* receiver, QEvent* e) override; }; #endif // DEBUGAPPLICATION_H
DebugApplication.cpp:
#include "debugapplication.h" DebugApplication::DebugApplication(int argc, char** argv) : QGuiApplication(argc, argv) { } bool DebugApplication::notify(QObject * receiver, QEvent* e) { try { return QGuiApplication::notify(receiver, e); } catch (std::exception & ex) { qFatal("Error %s sending event %s to object %s (%s)", ex.what(), typeid(*e).name(), qPrintable(receiver->objectName()), typeid(*receiver).name() ); } catch (...) { qFatal("Error <unknown> sending event %s to object %s (%s)", typeid(*e).name(), qPrintable(receiver->objectName()), typeid(*receiver).name()); } return false; }
And in main.cpp
qInstallMessageHandler( myMessageOutput ); // method to write messages to file. DebugApplication app( argc, argv ); // Some initialisation code... QQuickView view; // Crashes on this line. view.rootContext()->setContextProperty( QStringLiteral( "contentHandler" ), (QObject *)(new contentLoader( view.rootContext(), &app )) ); view.setSource( QUrl( QStringLiteral( "qrc:/contentloader.qml" ) ) ); view.show(); // more stuff return app.exec();
if I make
app
aQGuiApplication
it works fine. But if I make it aDebugApplication
it crashes at theQQuickView *view;
line without explanation.I will be just as happy with any other method of logging exceptions in the application! Basically my application crashes intermittently with no pattern or in no particular place and I'd like a way of logging info about why and where it crashed, but a regular
try... catch
just doesn't work, it just dies without falling into thecatch
.It will display (but not log) an error message if I run in debug mode, but in release mode it just says "Process killed by signal" in QTCreator's Application output. Since I have never been able to recreate this crash myself, having an error in Debug mode doesn't help.
I also have a call to
qInstallMessageHandler()
which allows me to outputqDebug()
messages to a file but that doesn't help in this case unless I can catch the crash when it happens to write the output. -
I don't know if this has anything to do with the crash, but your DebugApplication lacks Q_OBJECT macro.
-
Hi and welcome to devnet,
You constructor signature is wrong.
argc must be a reference to an int not an int.
-
Hi and welcome to devnet,
You constructor signature is wrong.
argc must be a reference to an int not an int.
Thanks! Well that got me past that problem, my application is now running!
However, overriding the notify() method did nothing... My application still crashes at the exception code without an error message if I run in Release mode.
In debug mode I get this, which is what I'd expect
ASSERT failure in QList<T>::operator[]: "index out of range", file /opt/ti/processor-sdk-linux-am335x-evm-04.03.00.05/linux-devkit/sysroots/armv7ahf-neon-linux-gnueabi/usr/include/qt5/QtCore/qlist.h, line 545
Process killed by signalBut in release mode just
Process killed by signal
Code to cause exception is:
QStringList stringlist {"hello"}; qDebug() << "String 2 is " << stringlist[2];
.. and it's in a backend handler for a QML splash screen.
(Not sure if I should make this another question or not)
-
Qt does not raise exceptions, so you cannot catch them.
-
Right - thanks for the info guys...
So it doesn't raise exceptions, but does it do anything when the application crashes that could be used to determine what happened?
I accept might be a bug in the code, unfortunately at the moment I'm at a loss to find where it is as it seems to happen randomly and rarely, and with seemingly no pattern.
-
Do you have a lot of containers in your application ?
-
From the crash we know it's one of the QList access that is at fault. Are you doing unchecked access in some specific files ?
-
From the crash we know it's one of the QList access that is at fault. Are you doing unchecked access in some specific files ?
@SGaist Ahh - maybe I didn't explain myself properly. The Assert failure error message that I put in the message above was actually just a result of my attempt to cause an exception or error message to appear or be logged, so I can have it in place to diagnose the "real" error when it occurs. That could be something different but at the moment the application is just dying.
-
@SGaist Ahh - maybe I didn't explain myself properly. The Assert failure error message that I put in the message above was actually just a result of my attempt to cause an exception or error message to appear or be logged, so I can have it in place to diagnose the "real" error when it occurs. That could be something different but at the moment the application is just dying.
-
Right - thanks for the info guys...
So it doesn't raise exceptions, but does it do anything when the application crashes that could be used to determine what happened?
I accept might be a bug in the code, unfortunately at the moment I'm at a loss to find where it is as it seems to happen randomly and rarely, and with seemingly no pattern.
@komodosp said in Catch exceptions in QT/C++ (QGuiApplication) (override notify() method?):
So it doesn't raise exceptions, but does it do anything when the application crashes that could be used to determine what happened?
No, by itself containers do not attempt to do anything, that's for performance reasons.
But you can get all the info you need by using asan (address sanitizer) or running the app under a debugger. Both ways will show you exactly where and why the crash is happening