Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How delete and deleteLater works with regards to signals and slots in Qt?

There is an object of class QNetworkReply. There is a slot (in some other object) connected to its finished() signal. Signals are synchronous (the default ones). There is only one thread.

At some moment of time I want to get rid of both of the objects. No more signals or anything from them. I want them gone. Well, I thought, I'll use

delete obj1; delete obj2; 

But can I really? The specs for ~QObject say:

Deleting a QObject while pending events are waiting to be delivered can cause a crash.

What are the 'pending events'? Could that mean that while I'm calling my delete, there are already some 'pending events' to be delivered and that they may cause a crash and I cannot really check if there are any?

So let's say I call:

obj1->deleteLater(); obj2->deleteLater(); 

To be safe.

But, am I really safe? The deleteLater adds an event that will be handled in the main loop when control gets there. Can there be some pending events (signals) for obj1 or obj2 already there, waiting to be handled in the main loop before deleteLater will be handled? That would be very unfortunate. I don't want to write code checking for 'somewhat deleted' status and ignoring the incoming signal in all of my slots.

like image 329
stach Avatar asked Feb 03 '11 15:02

stach


People also ask

How signals and slots work in Qt?

In Qt, we have an alternative to the callback technique: We use signals and slots. A signal is emitted when a particular event occurs. Qt's widgets have many predefined signals, but we can always subclass widgets to add our own signals to them. A slot is a function that is called in response to a particular signal.

What happens if we delete the subclass object of Qobject in slot?

The object will be deleted when control returns to the event loop.

Are Qt signals and slots thread safe?

It is generally unsafe to provide slots in your QThread subclass, unless you protect the member variables with a mutex. On the other hand, you can safely emit signals from your QThread::run() implementation, because signal emission is thread-safe.

Can we connect signal to signal in Qt?

This ensures that truly independent components can be created with Qt. You can connect as many signals as you want to a single slot, and a signal can be connected to as many slots as you need. It is even possible to connect a signal directly to another signal.


2 Answers

Deleting QObjects is usually safe (i.e. in normal practice; there might be pathological cases I am not aware of atm), if you follow two basic rules:

  • Never delete an object in a slot or method that is called directly or indirectly by a (synchronous, connection type "direct") signal from the object to be deleted. E.g. if you have a class Operation with a signal Operation::finished() and a slot Manager::operationFinished(), you don't want delete the operation object that emitted the signal in that slot. The method emitting the finished() signal might continue accessing "this" after the emit (e.g. accessing a member), and then operate on an invalid "this" pointer.

  • Likewise, never delete an object in code that is called synchronously from the object's event handler. E.g. don't delete a SomeWidget in its SomeWidget::fooEvent() or in methods/slots you call from there. The event system will continue operating on the already deleted object -> Crash.

Both can be tricky to track down, as the backtraces usually look strange (Like crash while accessing a POD member variable), especially when you have complicated signal/slot chains where a deletion might occur several steps down originally initiated by a signal or event from the object that is deleted.

Such cases are the most common use case for deleteLater(). It makes sure that the current event can be completed before the control returns to the event loop, which then deletes the object. Another, I find often better way is defer the whole action by using a queued connection/QMetaObject::invokeMethod( ..., Qt::QueuedConnection ).

like image 193
Frank Osterfeld Avatar answered Sep 19 '22 05:09

Frank Osterfeld


The next two lines of your referred docs says the answer.

From ~QObject,

Deleting a QObject while pending events are waiting to be delivered can cause a crash. You must not delete the QObject directly if it exists in a different thread than the one currently executing. Use deleteLater() instead, which will cause the event loop to delete the object after all pending events have been delivered to it.

It specifically says us to not to delete from other threads. Since you have a single threaded application, it is safe to delete QObject.

Else, if you have to delete it in a multi-threaded environment, use deleteLater() which will delete your QObject once the processing of all the events have been done.

like image 24
liaK Avatar answered Sep 18 '22 05:09

liaK