Results 1 to 7 of 7

Thread: Deleting the signal sender from a slot

  1. #1
    Join Date
    Nov 2016
    Posts
    4
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Deleting the signal sender from a slot

    I found by accident that my code deletes a QObject while it's emitting a signal. The deletion happens from a slot connected to that signal. My understanding has always been that such a thing is not allowed. Yet, I've seen no crashes or warning messages in this case. Am I wrong assuming such a thing is not allowed or is it just luck it's not crashing?

    A am using the latest Qt 5.7.

  2. #2
    Join Date
    Oct 2006
    Posts
    105
    Thanks
    13
    Thanked 4 Times in 4 Posts
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Deleting the signal sender from a slot


  3. #3
    Join Date
    Nov 2016
    Posts
    4
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Deleting the signal sender from a slot

    No, that thread discusses an unrelated topic.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Deleting the signal sender from a slot

    is it just luck it's not crashing?
    I'm guessing that you're just lucky. A signal to slot call is basically nothing more than an ordinary function call once the event loop invokes it. So if the last thing in the function is to emit the signal and the slot is the last one to be called, then the return from the signal is to code executing for an invalid instance, but if the stack unwinds properly and that instance is never used again, then you may have just gotten lucky.

    On the other hand, if there were more slots to be serviced after the one that deleted the instance, or the return from the emit call executed more code for that instance, then it probably would have crashed. Deleting a QObject is -supposed- to disconnect any slots connected to its signals but I am not sure if it also cleans up any pending slot invocations resulting from the signal. Disconnecting slots prevents future invocations.

    If you must delete a QObject-based class in a slot invoked by that instance, use deleteLater(). This allows the stack and event loop to clean up properly, and the instance will be deleted next time through the event loop.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Nov 2016
    Posts
    4
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Deleting the signal sender from a slot

    d_stranz, what you say makes perfect sense. If there was code following the emit statement that accesses the signalling object's state, it would certainly crash. Not my case though. As for having more slots connected, to be invoked following the deletion, I did such an experiment and those other slots simply don't get called. So, automatic disconnection does work in such a case.

    My line of thinking was like this:
    It's pretty simple for Qt developers to detect an object being deleted while it's emitting a signal and print a warning. Given that they don't, maybe it's not forbidden? I remember deleting a QObject from its event handler used to generate a warning message. It no longer does, presumably because it's now allowed. Unfortunately, the documentation is not explicit about either case.

    Using deleteLater() is an option, although I would rather avoid it in my case, as the code performing object destruction works with an abstract interface and doesn't know it's dealing with a QObject.

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,719
    Thanks
    259
    Thanked 760 Times in 750 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: Deleting the signal sender from a slot

    I did such an experiment and those other slots simply don't get called. So, automatic disconnection does work in such a case.
    Good to know. To be clear, you did something like this (with the connections in this order):

    connect signal to slot 1, which deletes the instance
    connect signal to slot 2, which uses the same instance
    ...
    then called emit signal in some class method of the object instance.

    And you observed that slot 1 is called, but the remaining ones were not.

    Correct? This implies that the connections were both deleted and the calls removed from the event queue, which is what you hope would happen.

    Using deleteLater() is an option, although I would rather avoid it in my case, as the code performing object destruction works with an abstract interface and doesn't know it's dealing with a QObject.
    Nothing wrong with adding a deleteLater() method to your abstract interface, with the default calling operator delete() and calling deleteLater() for QObject-based concrete classes.

    QObject instances emit a destroyed() signal immediately prior to destruction, so that's a way for Qt (and your own) code to clean up instance references.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #7
    Join Date
    Nov 2016
    Posts
    4
    Qt products
    Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Deleting the signal sender from a slot

    Quote Originally Posted by d_stranz View Post
    Good to know. To be clear, you did something like this (with the connections in this order):

    connect signal to slot 1, which deletes the instance
    connect signal to slot 2, which uses the same instance
    ...
    then called emit signal in some class method of the object instance.

    And you observed that slot 1 is called, but the remaining ones were not.

    Correct? This implies that the connections were both deleted and the calls removed from the event queue, which is what you hope would happen.
    Correct. Just to clarify, it's the emitter not the receiver that gets destroyed in slot 1. In slot 2 I only had a qDebug() and nothing else.

    Quote Originally Posted by d_stranz View Post
    Nothing wrong with adding a deleteLater() method to your abstract interface, with the default calling operator delete() and calling deleteLater() for QObject-based concrete classes.
    That's certainly an option.

Similar Threads

  1. Signal from multipal sender
    By suneel1310 in forum Qt Programming
    Replies: 7
    Last Post: 27th June 2013, 13:31
  2. Replies: 8
    Last Post: 7th November 2012, 15:10
  3. Replies: 3
    Last Post: 20th April 2011, 16:42
  4. Replies: 0
    Last Post: 15th December 2010, 07:18
  5. Replies: 3
    Last Post: 30th July 2010, 17:34

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.