views:

85

answers:

4

Here, my signal declaration:

signals:
    void mySignal(MyClass *);

And how I'm using it:

MyClass *myObject=new myClass();
emit mySignal(myObject);

Here comes my problem: Who is responsible for deletion of myObject:

1-)Sender code, what if it deletes before myObject is used? Dangling Pointer

2-)The slot connected to signal, what if there is no slot or more then one slot which are connected to the signal? Memory Leak or Dangling Pointer

How does Qt manage this sitution in its build-in signals? Does it use internal reference counting?

What are your best practices?

A: 

In a word (alright, function name) - deleteLater() :) All QObjects have it. It will mark the object for deletion, and this will then happen on the next event loop update.

leinir
A: 

For your first question, use QPointer

For your second question,

If I understood clearly, even if you are sending myObject, you still have the reference myObject in the class where you are emitting the signal. Then how will it be a memory leak or a dangling pointer? You can still access the myObject from the emitted class, isn't?

Hope am clear..

Edit :

From your comments I believe you are releasing/deleting the objects in the slots. Now I assume your problem is, what if the (memory releasing) slot gets called once,twice or not called at all.

You can use QPointer for that. From the Qt documentation,

Guarded pointers (QPointer) are useful whenever you need to store a pointer to a QObject that is owned by someone else, and therefore might be destroyed while you still hold a reference to it. You can safely test the pointer for validity.

An example from the Qt documentation itself,

     QPointer<QLabel> label = new QLabel;
     label->setText("&Status:");
     ...
     if (label)
         label->show();

the explanation goes on like this..

If the QLabel is deleted in the meantime, the label variable will hold 0 instead of an invalid address, and the last line will never be executed. Here QLabel will be your MyClass and label is your myObject. And before using it check for Nullity.

liaK
memory leak : when MyClass *myObject goes out of scope and no slot is connected. dangling pointer: one of slots delete object, and there is more then one slot.
metdos
+2  A: 

You can connect a signal with as many slots as you want so you should make sure that none of those slots are able to do something you would not want them to do with your object:

  • if you decide to pass a pointer as a parameter then you will be running in the issues you describe, memory management - here nobody can to the work for you as you will have to establish a policy for dealing with allocation/deletion. To some ideas on how to address this see the Memory Management Rules in the COM world.
  • if you decide to pass a parameter as a reference then you don't have to worry about memory management but only about slots modifying your object in unexpected ways. The ideea is not to pass pointers unless you have to - instead use references if you can.
  • if you decide to pass a const reference then, depending on your connection type, QT will pass the value of the object for you (see this for some details)
  • avoid any problems and pass by value :)

See also this question for some thoughts about passing pointers in signals.

Ando
A: 

At 1): The sender should take care. When sending the signal synchronously (instead of queued), the object is still alive when a receiver receives it. If the receiver needs to store it, only a QPointer would help, but then MyClass needs to derive from QObject, which looks wrong from the context. Anyway, that is a general lifetime issue, not very signal/slot-specific.

Alternatives: Use a value class and send it via const reference. If MyClass can have subclasses, pass a const QSharedPointer&

About deleteLater: deleteLater() doesn't help here. It would make queued connections any safer, and for direct connections it makes no difference. The one use where deleteLater() comes into play is if the receiver needs to delete the sender. Then one should always use deleteLater(), so the sender can complete what he was doing, which would otherwise crash.

Frank