Emitting signals from unrelated file causes break
-
I am attempting to emit multiple of the same signal in one function. Is this not possible, or am I doing it wrong?
Function with Emitting:void mydialog::testfunction(int t, int b) { emit testsignal("Hello, World!"); Sleep(2000); qDebug("Number: %d/%d", t, b); Sleep(10000); emit testsignal("Hello, World2!"); }
Calling it
QtConcurrent::run(this, &mydialog::testfunction, 9, 8);
Error thrown after the second emit (12 Seconds Later)
Exception thrown at 0x000000005391BFEE (Qt5Core.dll) in legit.exe: 0xC0000005: Access violation reading location 0x0000000000000023. occurred
If anymore info is needed then please ask.
-
@bludger With more testing and moving my tests to a new project I think i've come up with a more narrow scenario so you can help me easier. I've now switch from emitting from a closing dialog to emitting from an unrelated file, yet I still hit breakpoints during the emit, but this time even if I emit once.
emittertest.h#include <QObject> class emittertest : public QObject { Q_OBJECT public: void fnc(QString r); signals: void fnctest(QString); private: int value; };
emittertest.cpp
#include "emittertest.h" #include "qdebug.h" #include <windows.h> void emittertest::fnc(QString t) { qDebug() << t << "Thanks"; //emit fnctest("Word"); emit fnctest(QString("Rio")); }
My app's .cpp file
void gq(QString Rex) { while (true) { qDebug() << "Name:" << Rex << "Thread:" << QThread::currentThread(); Sleep(2000); } } void QtTestApp::myslot(QString t) { qDebug() << "Signal Emitted: " << t; } QtTestApp::QtTestApp(QWidget *parent) : QMainWindow(parent) { ui.setupUi(this); emittertest b; connect(&b, SIGNAL(fnctest(QString)), this, SLOT(myslot(QString))); QFuture<void> f2 = QtConcurrent::run(&b, &emittertest::fnc, QString("NAME")); }
Error
Exception thrown at 0x0000000063DFCE09 (Qt5Cored.dll) in QtTestApp.exe: 0xC0000005: Access violation reading location 0x000001FA8800F021. occurred
-
The emittertest variable gets out of scope before the signal is emitted. Upon connect you use the address of b so Qt's metasystem uses that address until the signal and slot are being disconnected. When leaving the constructor all local variables are going out-of-scope and so does b, meaning that the address of b became invalid.
A quick fix would be moving the local variable b to be a class member variable. Or making it a pointer instead so the object lives on the heap (make sure you delete it properly to avoid any memory leaks).class QtTestApp : public QMainWindow { Q_OBJECT .... private: emittertest m_b; }
Or as a pointer: (also a class member)
class QtTestApp : public QMainWindow { Q_OBJECT ... private: emittertest* m_b; }
-
@bludger Trying it your way and I get these errors
Severity Code Description Project File Line Suppression State Error C2065 'm_b': undeclared identifier QtTestApp C:\Users\Contempt\source\repos\QtTestApp\QtTestApp\QtTestApp.cpp 21 Severity Code Description Project File Line Suppression State Error C4430 missing type specifier - int assumed. Note: C++ does not support default-int QtTestApp c:\users\contempt\source\repos\qttestapp\qttestapp\QtTestApp.h 15 Severity Code Description Project File Line Suppression State Error C3646 'm_b': unknown override specifier QtTestApp c:\users\contempt\source\repos\qttestapp\qttestapp\QtTestApp.h 15
My QtTestApp.h
class QtTestApp : public QMainWindow { Q_OBJECT public: QtTestApp(QWidget *parent = Q_NULLPTR); private slots: void myslot(QString); private: emittertest m_b; Ui::QtTestAppClass ui; };
And I can not run emittertest::fnc() in a QtConcurrent thread anymore.
-
It's still a race condition as there is nothing stopping your
QMainWindow
destroying beforeQtConcurrent::run
finished. There is a way of making it work even withQtConcurrent
but it's harder than just using QThread: see https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/