Ayao "Alqualos" Kuroyuki (ayao) wrote,
Ayao "Alqualos" Kuroyuki
ayao

QObject auto-disconnect in destructor

It is pretty nice that QObject::~QObject() automatically disconnects everything connected to the object's slots. However, it would be pretty unwise to always rely on this useful feature. Here's one good example how it can screw up a seemingly harmless code.

Suppose you have some kind of networking class, say, MyProtocol. This class is a descendant of QObject that incorporates several fields, including a custom MyStream object. MyProtocol is also connected to the disconnected() signal of the socket used for network communication. Now MyStream has a destructor that sends some sort of "goodbye message" to the other end using the same socket. When this happens, the socket could realize that the connection is broken and emit disconnected(). Which would call the appropriate slot in the half-destructed MyProtocol:
class MyProtocol: public QObject {
Q_OBJECT
  // some other fields here
  MyProtocol protocol;
public:
  MyProtocol(QTcpSocket *socket);
private slots:
  void onDisconnected();
};

MyProtocol::MyProtocol(QTcpSocket *socket)
{
  connect(socket, SIGNAL("disconnected()"), SLOT("onDisconnected()"));
}

void MyProtocol::onDisconnected()
{
  // working with some fields here
}

class MyStream {
  QTcpSocket *socket;
public:
  ~MyStream();
};

MyStream::~MyStream() {
// this could trigger QAbstractSocket::disconnected()
socket->write("goodbye\n");
}

This could be a source of rather subtle bugs. Since MyStream destructor is called from the MyProtocol destructor, it can't be guaranteed that the MyProtocol object is still usable. And ~MyStream() doesn't use it directly! Instead, it works with the socket, which in turn can emit some signals, and some slots will get called, some of them possibly in the half-destructed MyProtocol!

How to deal with this? Easy. Disconnect all the signals as soon as you don't need them any more. Writing a custom destructor for MyProtocol that does it would work too. Too bad Qt doesn't provide a way to disconnect every signal connected to a particular object, only the other way around (all slots connected to the object signals). The hardest part of this kind of bugs is to figure out what happens, as the program could break at any point later due to memory corruption.
Tags: it, qt
Subscribe
  • Post a new comment

    Error

    Anonymous comments are disabled in this journal

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

  • 0 comments