Qt destructor call for closed widget
Solution 1
Setting Qt::WA_DeleteOnClose
means qt can delete anytime after you call close()
because qt uses deleteLater()
internally. You can ensure the deletion using QObject::destroyed()
signal.
Solution 2
QCoreApplication::processEvents explicitly skips delete on close events. You need to pass QEventLoop::DeferredDeletion to processEvents(). i.e. QCoreApplication::processEvents(QEventLoop::DeferredDeletion);
axe
Updated on July 20, 2022Comments
-
axe almost 2 years
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 commandsclose *; get something;
the program crashes becauseget something
is called before destructor for that widget, so it tries to access data deleted byclose *
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 outputtest() 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?
-
axe over 12 yearsI was able to fix it by adding deleteLater() function call for that widget in closeEvent function. But I would like to understand the solution. Could you please explain that in more details or provide a link that explains that technique?
-
axe over 12 yearsI want to ensure that Qt will delete the at the moment I finished executing my first command. How can I make it?
-
useraged over 12 yearsIf you can close it you can delete it too. Don't set
Qt::WA_DeleteOnClose
flag and simply delete it. You'll be sure then. -
axe over 12 yearsThe application is really huge, then I would need to ensure that I delete it from everywhere where close is called. I wouldn't like to make much changes there. This might result in memory leak. Isn't it possible to force Qt to delete the objects marked as DeleteOnClose?
-
useraged over 12 yearsAccording to qt documentation, you can use
sendPostedEvents()
too. doc.qt.nokia.com/latest/qcoreapplication.html#processEvents -
axe over 12 yearsprocessEvents() and sendPostedEvents() doesn't help. If I switch to manual deletion it works fine, but when I replace
delete obj
withobj->deleteLater(); QCoreApplication::sendPostedEvents();
or processEvents() it doesn't work again. -
useraged over 12 yearsManual deletion does not result memorly leaks if code is properly written. Normally
processEvents
should delete that object. BecausedeleteLater
sends an event to widget and callingprocessEvents
with no argument should handles all posted events. It can be a bug in qt. I think you should write this problem to [email protected] maillist. -
axe over 12 yearsIt can result to memory leak, because I'm not sure where it can be closed from, to put delete everywhere. And yes, code is not properly written :) I'll try nokia forums. Thanks a lot for your help.