[Solved] crash. QObject::connect in a constructor of a static object instance.
-
wrote on 25 Apr 2012, 19:59 last edited by
I'm trying to find out why my app crashes for the whole day. A picture worth thousands of words, so take a look at this code:
@class SandboxedAppStat : public QObject
{
Q_OBJECTprivate slots:
void pidsTimerTimeout();public:
QTimer m_PidsTimer;SandboxedAppStat(QObject *parent = NULL);
};
void SandboxedAppStat::pidsTimerTimeout()
{
qDebug() << "whatever";
}SandboxedAppStat::SandboxedAppStat(QObject *parent)
: QObject(parent)
{
bool b = QObject::connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));
m_PidsTimer.start(500);
}@@class SandboxedApp : public QObject
{
Q_OBJECTprivate:
static SandboxedAppStat SandboxedAppStat1;
};SandboxedAppStat SandboxedApp::SandboxedAppStat1;
@Actually what I'm trying to do, is to simulate static constructor behavior in C++. I want
@QObject::connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));
m_PidsTimer.start(500);@to be called as soon as the static member SandboxedAppStat1 initializes. That's why the code shown above is in the constructor of SandboxedAppStat.
However, my problem is that when I run the program, it crashes as soon as it reaches the line @connect(&m_PidsTimer), SIGNAL(timeout()), this, SLOT(pidsTimerTimeout()));@with error code c0000005 (access violation I guess).
here's the screenshot http://dl.dropbox.com/u/3055964/Untitled.gifIf I declare SandboxedAppStat as a non static variable, then there is no crash and no errors. everything works fine.
First I thought that crash reason could be the fact that, static members are initialized too early for QObject::connect to be able to be called, that's why I updated SandboxedAppStat constructor with the following code:@ auto *t = this;
QtConcurrent::run([&] () {
Sleep(3000);
bool b = QObject::connect(&(t->m_PidsTimer), SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
t->m_PidsTimer.start(500);
});
@As you can see, QObject::connect executes after 3 seconds when static SanboxedAppStat is initialized, but this didn't help either, the program crashes after 3 seconds.
I'm really confused, I don't understand what can be the cause of this problem. Can't we use signal/slots in a static object instances?I'm using Qt 4.8.0 with MSVC 2010.
Thanks
-
wrote on 25 Apr 2012, 22:52 last edited by
For the first method, the problem might be that the metaobject needed for connecting the slot is not yet initialized (See "the static order initialization fiasco in the C++ FAQ":http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.14).
It doesn't crash with gcc on linux, but it prints the error:
@QObject::startTimer: QTimer can only be used with threads started with QThread@And for the second method, with the lambda, I think the crash is caused by the variable t going out of scope, and not pointing to a valid pointer at the time the connect call occurs. You could pass it as a binded parameter to run:
@QtConcurrent::run([&] (decltype(this) t) {
bool b = QObject::connect(&(t->m_PidsTimer), SIGNAL(timeout()), t, SLOT(pidsTimerTimeout()));
t->m_PidsTimer.start(500);}
, this);
@ -
wrote on 26 Apr 2012, 07:46 last edited by
@alexisdm thank you for your answer. You were right about the lambdas, I followed your suggestion and didn't had a crash after that.
However, about static order initialization, as far as I'm aware, this can occur only if a static object/function tries to access another static object in different compilation unit. Does this mean that Qt meta object stuff is accessing my static member from a static function? And if so, why? what's the reason behind this?Thanks
-
wrote on 26 Apr 2012, 10:01 last edited by
BTW, here's a simple project consisting of only one header and one source file to reproduce the problem. http://dl.dropbox.com/u/3055964/untitled1.zip
-
wrote on 26 Apr 2012, 16:25 last edited by
The static data being accessed is the meta information generated by the moc for your SandboxedAppStat class, in the file moc_yourfilename.cpp.
You could try printing the class name to confirm the problem:
@SandboxedAppStat::SandboxedAppStat(QObject *parent)
: QObject(parent)
{
std::cout << Q_FUNC_INFO << std::endl; // just to confirm we entered the function
std::cout << "class name: " << SandboxedAppStat::staticMetaObject.className() << std::endl;
}@
I tested and it does crash with msvc2010, but works fine with gcc.
1/6