There is application that handles text commands. I have a Qt widget that is closed with some close *
command. Qt::WA_DeleteOnClose
attribute is set for that widget, it receives closeEvent, but destructor for that object is called later (I guess on idle). If I have two commands
close *; get something;
the program crashes because get something
is called before destructor for that widget, so it tries to access data deleted by close *
command. How can I force Qt to call destructors? QCoreApplication::processEvents()
after close command doesn't help.
I've got this problem after changing qt version to 4.7.2 from 4.3.3. There is no multithreading here.
Thanks in advance.
added
Here is the code example.
test *t = new test();
t->show();
std::cout << "before deleteLater()" << std::endl;
t->deleteLater();
std::cout << "after deleteLater()" << std::endl;
QCoreApplication::sendPostedEvents();
QCoreApplication::processEvents();
std::cout << "after processEvents()" << std::endl;
test class is derived from QDialog. It prints test()
in constructor and ~test()
in destructor. This code gives the following output
test()
before deleteLater()
after deleteLater()
after processEvents()
~test()
According to Qt documentation it should delete the object before last cout, am I right? Looks like a bug in Qt, does anybody know anything about it? Any workaround?
I asked the question in Qt mailing list, but still waiting for an answer.
Thanks.
one more update
This code
Dialog::~Dialog() {
std::cout << "~test()" << std::endl;
}
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
Dialog* dlg = new Dialog();
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->show();
dlg->close();
std::cout << "before sendPostedEvents()" << std::endl;
QCoreApplication::sendPostedEvents();
std::cout << "after sendPostedEvents()" << std::endl;
return app.exec();
}
prints this
before sendPostedEvents()
after sendPostedEvents()
~test()
but as soon as I add closeEvent handler and call deleteLater() in that handler function sendPostedEvents starts deleting deferred objects.
void Dialog::closeEvent(QCloseEvent* ev) {
deleteLater();
QWidget::closeEvent(ev);
}
prints this before sendPostedEvents() ~test() after sendPostedEvents()
Can anybody explain what the hell is going on there? Is it just a bug? Can I use that as a workaround?
How does this work? Shouldn't Qt call deleteLater() automatically, after closeEvent is accepted if CloseOnDelete attribute is set?
QCoreApplication::processEvents explicitly skips delete on close events. You need to pass QEventLoop::DeferredDeletion to processEvents(). i.e. QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
Setting
Qt::WA_DeleteOnClose
means qt can delete anytime after you callclose()
because qt usesdeleteLater()
internally. You can ensure the deletion usingQObject::destroyed()
signal.