Page 1 of 2 12 LastLast
Results 1 to 20 of 29

Thread: Qt deleteLater() force to delete

  1. #1
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Qt deleteLater() force to delete

    Hi all,

    I'm porting application from older version of Qt to 4.7.2 and I found one problem there.
    deleteLater() function is supposed to schedule object for deletion and object should be deleted when control next time enters to the event processing loop, but it doesn't work for me.
    Here is the code
    Qt Code:
    1. test *t = new test();
    2. t->show();
    3. std::cout << "before deleteLater()" << std::endl;
    4. t->deleteLater();
    5. std::cout << "after deleteLater()" << std::endl;
    6. QCoreApplication::sendPostedEvents();
    7. QCoreApplication::processEvents();
    8. std::cout << "after processEvents()" << std::endl;
    To copy to clipboard, switch view to plain text mode 
    Class test 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?

    Of course I could do manual delete, but application is huge and it would require too much changes, I wouldn't like to change too much things as it may cause another problems.

    Thanks.

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    Calling processEvents() doesn't trigger deffered deletion. The application really needs to enter the event loop.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  3. #3
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    How can I force it? Is there any way?
    Here is the problem:
    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 widget still receives events and it tries to access data deleted by close * command. I would like to force Qt to delete all pending objects after command completion.

    I guess previously it was entering event processing loop, but something is changed.

    Any ideas how to make it work?
    Thanks.
    Last edited by axe; 18th August 2011 at 09:12.

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    Quote Originally Posted by axe View Post
    How can I force it?
    Why would you want to force it?

    the program crashes because "get something" is called before destructor for that widget, so widget still receives events and it tries to access data deleted by close * command. I would like to force Qt to delete all pending objects after command completion.
    Then either schedule execution of "get something" and return to the event loop or simply have the closeEvent for the widget (or some other appropriate place) contain code that will set a flag that is checked before the widget tries to access this data. Or use one of available smart pointer classes.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    wysota

    The problem appeared after updating Qt version from 4.3.3 to 4.7.2. I wouldn't like making such changes, the code is really huge and every simple change may result in thousands of bugs. I would like to fix the problem with minimum amount of changes. I guess previously Qt was forced to delete the object by calling sendPostedEvents() (at least comment says that), but currently this doesn't work.

    Here is the code
    Qt Code:
    1. // Send queued events (including deferred deletions) to all QObjects
    2. // unless we have to preserve view objects
    3. if (deleteImmediately)
    4. QCoreApplication::sendPostedEvents(NULL, -1);
    To copy to clipboard, switch view to plain text mode 

    This code looks strange to me, however this is what we have and this is what was working before.
    Do you mean there is no way to force it?
    Last edited by axe; 18th August 2011 at 10:22.

  6. #6
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    I have code that deletes deferred object by calling sendPostedEvents for Qt 4.3.3, but this code doesn't work for Qt 4.7.2. Also I tried to make a simple application that works and I couldn't make it work even with Qt 4.3.3, sendPostedEvents doesn't call any destructors. It's difficult to track everything what is going on in original application before it calls sendPostedEvents and deletes deferred object, does anybody know anything about it? In what situations it can invoke deferred delete? Any useful information that will help me to debug?
    Can it depend on some project options or predefined macros? Is there any known bug? Anything...


    Added after 1 40 minutes:


    Looks like sendPostedEvents delete deferred objects only if it's not called from Qt event handler. Our events are coming from Tcl, so they are not called from Qt main event loop, seems that this is the reason that it works, but here is another problem.
    This code
    Qt Code:
    1. Dialog::~Dialog() {
    2. std::cout << "~test()" << std::endl;
    3. }
    4.  
    5. int main(int argc, char* argv[]) {
    6. QApplication app(argc, argv);
    7. Dialog* dlg = new Dialog();
    8. dlg->setAttribute(Qt::WA_DeleteOnClose);
    9. dlg->show();
    10. dlg->close();
    11. std::cout << "before sendPostedEvents()" << std::endl;
    12. QCoreApplication::sendPostedEvents();
    13. std::cout << "after sendPostedEvents()" << std::endl;
    14. return app.exec();
    15. }
    To copy to clipboard, switch view to plain text mode 
    prints
    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.
    Qt Code:
    1. void Dialog::closeEvent(QCloseEvent* ev) {
    2. deleteLater();
    3. QWidget::closeEvent(ev);
    4. }
    To copy to clipboard, switch view to plain text mode 
    before sendPostedEvents()
    ~test()
    after sendPostedEvents()
    Can anybody explain what the hell is going on there? I have no idea what's that. Is it just a bug? Can I use that workaround?
    How does this work? Shouldn't Qt call deleteLater() automatically, after closeEvent is accepted if CloseOnDelete attribute is set?
    Last edited by axe; 18th August 2011 at 14:43.

  7. #7
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    No, it's not a bug, I think I remember this change being introduced or at least mentioned. You are abusing deleteLater() for something it wasn't meant and hence you can't expect sane response from Qt.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  8. #8
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    OK. Let me go deeper into details.
    There is a GUI application that handles Tcl commands. Tcl commands are handled by library written by another team, so we can't touch that. If you execute one command then library will return control to Qt event loop, but if you execute more then one command then library will return control to the main loop only when all commands are finished. Now, there is command that closes some views, and those views are receiving events (Qt events). Those views have DeleteOnClose attribute set, and after close command is executed those views are closed and closeEvent() virtual function is executed immediately, but the object is not deleted yet. The problem is that this view continues to receive Qt signals and it crashes, because some references are already deleted. Also those behaviour was causing memory issues, because if you run big script it will not clean the memory untill it will not finish the job, that is a problem and I see someone fixed this issue by adding sendPostedEvents() function call after close. Now Qt version is changed and it doesn't work anymore, what solutions do I see?
    1. Disconnect all slots from widget in closeEvent function. This will solve the problem, but as destructor call for this widget is deferred, this will return us to our old memroy issue. So it's not complete solution.
    2. Add deleteLater() call as described in my previous post. This will solve the problem again, it will solve the problem with memory too, but this looks unstable to me, I'm not kind of person who likes solution like that. I don't see any gurantee from Qt.
    3. Remove DeleteOnClose attribute and do manual delete. In some situations it is required to leave the object alive after closing it, because it contains some data that is required by post-callbacks. If I switch to manual delete then I wouldn't be able to defer deletion of the object (I mean I wouldn't be able to do that without changing megabytes of source code).

    So the best solution for me would be to find a portable way to force Qt to delete deferred objects, as it was done before (not portably).
    Any suggestions?

  9. #9
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    Can't you just call "delete" on the object instead of using deleteLater()?
    Last edited by wysota; 18th August 2011 at 19:42.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  10. #10
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    Well, there is no deleteLater() call at all, deleteLater() is called automatically by closeEvent when DeleteOnClose attribute is set as far as I understood from Qt doc.
    Actually I can't delete that simple. There is boolean flag named immediateDelete, if it is set then sendPostedEvents is called and in older Qt version it does delete the deferred object, so everything works fine. I can replace this function call with manual deletion, but I'm not sure what will happen if Qt will try to delete this deferred object. If I remove DeleteOnClose attribute then I would need to delete all objects manually, but the code is so huge that it's really impossible to do not forget about anything. I wouldn't like making such changes.

  11. #11
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    If not, then you need to rewrite a piece of code --- perform deletion (using deleteLater), schedule the next instruction (e.g. using invokeMethod() or a 0-timeout timer) and return to the event loop. You can have a look at [wiki]Keeping the GUI Responsive[/wiki] article to learn some details.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  12. #12
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    But how can I return to the main loop? This 3rd party library doesn't return control to the main loop, untill all commands are not processed. If sendPostedEvents doesn't return control to the main loop as well then how can I do that?

  13. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    I don't have definite answers for your problems. Maybe you need to dig deeper into how the library works or maybe you need to replace it with a better solution. A TCL interpreter is publically available, maybe it's easier to use it instead of the offending library. Or file a bug report to the library maintainers.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  14. #14
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    Am I getting you right?
    1. Qt deletes deferred objects ONLY when it returns to main loop.
    2. The only way to return to the main loop in Qt is to return from function that is called from that main loop.
    Based on those two points we can't force Qt to delete deferred objects at any moment.

    Then one more question, what if I manually delete deferred object? Does Qt delete it from deferred list or it may try to delete it as well?

  15. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    Quote Originally Posted by axe View Post
    1. Qt deletes deferred objects ONLY when it returns to main loop.
    That's the point of deferred deletion -- make sure nobody is using the object anymore (which means all events are delivered and all signals processed). See the quote below.

    2. The only way to return to the main loop in Qt is to return from function that is called from that main loop.
    Based on those two points we can't force Qt to delete deferred objects at any moment.
    You could try the obsolete processEvents(QEventLoop::DeferredDeletion) but I suspect it will fail. The docs say:
    Quote Originally Posted by Qt docs
    Note that entering and leaving a new event loop (e.g., by opening a modal dialog) will not perform the deferred deletion; for the object to be deleted, the control must return to the event loop from which deleteLater() was called.
    I can only explain that Qt keeps an internal count of nesting event loop calls so the numbers have to match here (thus cheating by re-entering the same event loop will not work and in addition you'll get a warning or even a crash).

    Then one more question, what if I manually delete deferred object? Does Qt delete it from deferred list or it may try to delete it as well?
    You can do that. Qt will remove deferred deletion from the event queue (along with all pending events for the object).
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  16. #16
    Join Date
    Mar 2011
    Location
    Hyderabad, India
    Posts
    1,882
    Thanks
    3
    Thanked 452 Times in 435 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows
    Wiki edits
    15

    Default Re: Qt deleteLater() force to delete

    May be I didn't get the complete picture yet, if you want to delete immediately, can't you just call delete on the object directly, instead of calling deleteLater() on the object.

  17. #17
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Qt deleteLater() force to delete

    May be I didn't get the complete picture yet, if you want to delete immediately, can't you just call delete on the object directly, instead of calling deleteLater() on the object.
    (few posts above)
    I can replace this function call with manual deletion, but I'm not sure what will happen if Qt will try to delete this deferred object. If I remove DeleteOnClose attribute then I would need to delete all objects manually, but the code is so huge that it's really impossible to do not forget about anything. I wouldn't like making such changes.

  18. #18
    Join Date
    Aug 2011
    Posts
    15
    Thanks
    2

    Default Re: Qt deleteLater() force to delete

    Quote Originally Posted by wysota View Post
    You could try the obsolete processEvents(QEventLoop::DeferredDeletion) but I suspect it will fail. The docs say:
    It works, but is it guaranteed to work? Actually I agree, documentation says that it shouldn't, but on the other hand this is what it is supposed to do. Anyway, it is obsolete function and not recommended for use, I guess it will be removed in next Qt versions. So despite the fact that it works it's better to do not use QEventLoop:eferredDeletion.

    What remains? Looks like the only reasonable solution is manual deletion in this situation.

  19. #19
    Join Date
    Sep 2009
    Location
    Wroclaw, Poland
    Posts
    1,394
    Thanked 342 Times in 324 Posts
    Qt products
    Qt4 Qt5
    Platforms
    MacOS X Unix/X11 Windows Android

    Default Re: Qt deleteLater() force to delete

    Anyway, it is obsolete function and not recommended for use, I guess it will be removed in next Qt versions. So despite the fact that it works it's better to do not use QEventLoop:eferredDeletion.
    I would not rely on "not recommended" methods too, so I guess you've reached a point when you won't escape some refactoring (implement manual deletion, use of safe pointers for shared data etc).

  20. #20
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: Qt deleteLater() force to delete

    It won't be removed until the end of days of Qt4. But it's obsolete and potentially dangerous. If you want, you can make your own mechanism for deferred deletion, it's not a big deal.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. Let QThread delete itself with deleteLater();
    By Lodorot in forum Qt Programming
    Replies: 1
    Last Post: 24th February 2010, 16:48
  2. To use or not to use: deleteLater()
    By codeslicer in forum Qt Programming
    Replies: 11
    Last Post: 11th July 2009, 21:43
  3. Replies: 4
    Last Post: 19th February 2009, 11:10
  4. QT deleteLater again.
    By bunjee in forum Qt Programming
    Replies: 1
    Last Post: 10th May 2008, 22:36
  5. Qt Deletelater
    By bunjee in forum Qt Programming
    Replies: 2
    Last Post: 8th January 2008, 16:58

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.