About incomplete destruction of a signal receiver and the status of its connection

  • Qt documentation indicates that if either the emitter or the receiver of a signal is destroyed, then the connection is broken. In strict C++ terms, the life time of an object ends when its destructor starts. So the documentation most probably means that a call to emit will have no effect once the emitter or the receiver destructor is completed. What happens if the destructor is not completed is the subject my post.

    Running the following example on my machine (Linux 32, Qt 5.1.1) showed me that the slot is called while the receiver is only partially destroyed (i.e., only the most derived part of the destructor is performed):
    #include <QtCore/QObject>
    #include <QtCore/QDebug>

    #ifndef RECEIVERS_HPP
    #define RECEIVERS_HPP

    class ReceiverOldSyntax: public QObject {

    ReceiverOldSyntax() { mEmitter = new QObject(); connect(mEmitter, SIGNAL(destroyed()), this, SLOT(showMessage()), Qt::UniqueConnection);}
    virtual ~ReceiverOldSyntax() { delete mEmitter; }

    QObject *mEmitter;

    protected slots:
    void showMessage() { qDebug() << "Still connected in the destructor"; }

    class ReceiverNewSyntax: public ReceiverOldSyntax {

    ReceiverNewSyntax() { mEmitter = new QObject(); connect(mEmitter, &QObject::destroyed, this, &ReceiverNewSyntax::showMessage, Qt::UniqueConnection); }


    #include "Receivers.hpp"

    int main()
    const ReceiverOldSyntax *const or = new ReceiverOldSyntax();
    delete or;

    const ReceiverNewSyntax *const nr = new ReceiverNewSyntax();
    delete nr;

    return 0;

    This is what I expect. Indeed, since ~QObject() is not called prior to signal emission, I don't see how Qt could find a way to disconnect QObjects at this stage (but if there is way, please just tell me!)

    In the above example, I used both the old and new syntax to see if there was any difference, and I saw, as expected, no differences.

    Here is my question: Is the above use of a signal-and-slot mechanism in a destructor prohibited in the sense
    that it may lead to something undefined?

    I am asking this because I noticed that the connection is broken with the old syntax but not with the new syntax when working with a similar but more involved example. (The problem could be elsewhere, of course).

    Thanks in advance for your insight,

Log in to reply