What are the lifetimes of Qt Objects?
Such as:
QTcpSocket *socket=new QTcpSocket();
When socket will be destroyed? Should I use
delete socket;
Is there any difference with:
QTcpSocket socket;
I couldn't find deep infromation about this, any comment or link is welcomed.
Qt uses parent-child relationships to manage memory. If you provide the QTcpSocket object with a parent when you create it, the parent will take care of cleaning it up. The parent can be, for example, the GUI window that uses the socket. Once the window dies (i.e. is closed) the socket dies.
You can do without the parent but then indeed you have to delete the object manually.
Personally I recommend sticking to idiomatic Qt and using linking all objects into parent-child trees.
Objects allocated with new must be released with delete.
However, with Qt, most objects can have a parent, which you specify as an argument to the constructor. When the parent is deleted, the child objects get deleted automatically.
If you don't want to pass a parent for some reason (because there is no QObject where it makes sense to own the socket object), you can also use a QSharedPointer to manage the lifetime.
Related
I'm using threaded application written in Qt (C++).
I need to make get/post request very often from separate threads.
Qt doc says:
One QNetworkAccessManager instance should be enough for the whole Qt
application. Since QNetworkAccessManager is based on QObject, it can
only be used from the thread it belongs to.
Is static thread_local QNetworkAccessManager good choice for my purpose?
No, not a good choice.
You shouldn't create static or global QObject subclass instances, because you generally need them to be created after the Qt application object has been created (a lot of Qt stuff depends on the application object existing already). C++ does not really provide very good control over when static objects are actually created, and here you want to have that control.
Just use a pointer and new to create the QNetworkAccessManager instance, as many of them as you want. You could create them in the right thread directly, or you could create them in some other (usually main) thread and move them to the right thread.
To get them destroyed properly, when they don't have a natural parent (because the parent must live in the same thread!), connect the their thread's QThread::finished signal to the objects QObject::deleteLater slot, and they will get cleanly deleted when the thread finishes.
If you want a plain function, which uses the current thread's QNAM instance, you could have thread-local static pointer. Something like
static thread_local *thread_qnam;
void myfunc() {
if (!thread_qnam) {
thread_qnam = new QNetworkAccessManager;
connect(QThread::currentThread, &QThread::finished(), thread_qnam, &QObject::deleteLater);
// Whatever other setup you need.
// It'd probably be good idea to wrap this in a function.
}
// Use thread_qnam...
}
QTcpSocket * QTcpServer::nextPendingConnection () [virtual]
The socket is created as a child of the server, which means that it is
automatically deleted when the QTcpServer object is destroyed. It is
still a good idea to delete the object explicitly when you are done
with it, to avoid wasting memory.
In my application, a QTcpServer lives for a long time (it disconnects from host when connection is closed but is never destroyed unless the program exits), and it accepts a lot of QTcpServer::nextPendingConnection and takes a lot of memory.
How should I delete the old QTcpSocket object before switching to the next pending one to save memory, while at the same time avoid double-delete?
Is delete ok in this case?
Is delete ok in this case?
Yes, thanks to the cleverness of Qt's object design.
In particular, QTcpSocket derives (eventually) from Object, and the QObject destructor method contains this code at the end:
if (d->parent) // remove it from parent object
d->setParent_helper(0);
So deleting the QTcpSocket object will automagically remove the QTcpSocket from the children-list of its parent object (in this case, the QTcpServer), so there will be no double-delete when the QTcpServer object is destroyed.
I have done something like this:
//in the mainwindow's constructor
QThread *thr = new QThread;
soundWorker * work = new soundWorker;
connect(this,SIGNAL(playsound()),work,SLOT(process()));
work->moveToThread(thr);
thr->start();
Shall I delete thr and work at the deconstructor of mainwindow?
You can use the default Qt way of managing memory by assigning a parent to the QThread, i.e. do this:
QThread *thr = new QThread(this);//the mainwindow's is now the thread parent
In Qt, parents are responsible for managing the memory of their children. Thus, the QThread will be automatically deleted when needed.
Then, for your soundWorker, you have a few different solutions. If its lifetime is the same as your mainwindow, as you hint when you ask if you should delete it in the destructor of the mainwindow, you could simply make it a non-pointer member, and its storage duration would then become automatically handled.
The parent thing is specific to Qt though. In general, when you deal with memory yourself, you should resort to wrappers (such as smart pointers) that enables RAII.
Further reading: Qt Trees and ownership model
You can use the QThread::finished() signal in order detect the moment you wish to release the QThread pointer. Same thing could be done with QObject pointers which were moved to the new thread.
Considering that the moment of closing the main window is the moment of closing the whole application and considering that you don't need to further do processing after the application was closed, you can pass the main window pointer as a parent to the QThread by either passing it to the constructor or using QObject::setParent.
Releasing the resources acquired inside the thread handled by QThread must be handled separately as you can't make the QThread object a parent of a resource managed by it - QThread lives in the thread where it was created and not in the thread it manages.
More details here.
Here is my sample qt connect statement
connect(pHttpFetch, SIGNAL(Fetched(QByteArray)), this, SLOT(PrintData(QByteArray)));
Here the signal of first object is connected to the slot of the invoking(which makes the connect call) object.
I have the following things
The first object is a local object. The object is killed when control goes out of scope.
The invoking object will stay in memory throughout the application memory.
As I don't need the first object, is it fine to make it a local object ? ( I assume Qt magically keeps the object in memory)
Should I make a shared pointer to hold the object. Will destroy the object when not required ?
According to the Qt documentation
All signals to and from the object are automatically disconnected, and any pending posted events for the object are removed from the event queue.
And no, Qt doesn't "magically" keep the object in memory.
An object that doesn't exist anymore can't send signals. You should allocate memory for this object and keep a reference to it. Remember that if you gave your QObject a parent, then this parent will automatically handle the deletion of their child (but if you don't provide a parent, you'll have to delete it manually or use the deleteLater() slot of QObject)
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:
Sender code, what if it deletes before myObject is used? Dangling Pointer
The slot connected to signal, what if there is no slot or more than one slot which is connected to the signal? Memory Leak or Dangling Pointer
How does Qt manage this situation in its build-in signals? Does it use internal reference counting?
What are your best practices?
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.
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.
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.
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.