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.
Related
The last weeks I read a lot about RAII and thought that I should start using smart pointers in my applications. As an example I tried to modify one of my applications. It captures frames from a webcam in a thread, performes image processing in another thread and displays the processed and unprocessed images in QT widgets. One central Object is the CCameraHandler which controls the capturing thread and image processing thread. Up to this point I used 4 plain pointers as members in this class:
CCameraCapture* m_CameraCapture;
CImageProcessor* m_ImageProcessor;
QThread* m_CameraCaptureThread;
QThread* m_ProcessingThread;
In the constructor of CCameraHandler I created the Instances using new and moved the capture object to the thread:
m_CameraCaptureThread= new QThread();
m_CameraCapture= new CCameraCapture();
//Move camera capture object to thread
m_CameraCapture->moveToThread(m_CameraCaptureThread);
That approach worked nicely. Now I wanted to a first test with QScopedPointer and tried to change m_CameraCapture to a QScopedPointer using
QScopedPointer<CCameraCapture> m_CameraCapture;
and initializing it with CameraCapture(new CCameraCapture()) in the initialization list. It compiled nicely and works as it should but when I close the application an the destructors are called I get an error from Qt:"Cannot send events to objects owned by a different thread. Current thread 5ff590. Receiver '' (of type 'CCameraCapture') was created in thread 4b7780" I guess that it has to do with the m_CameraCapture->moveToThread(m_CameraCaptureThread); where I now move a scoped pointer. Is the QScopedPointer automatically parented by CCameraCapture? So far I used
//This connections guarantees that the m_CCameraCapture and m_CameraCapture are deleted after calling QThread::exit()
QObject::connect(m_CameraCaptureThread, SIGNAL(finished()), m_CameraCaptureThread, SLOT(deleteLater()));
QObject::connect(m_CameraCaptureThread, SIGNAL(finished()), m_CameraCapture, SLOT(deleteLater()));
to delete thread an worker when camera capturing is stopped. If m_CameraCapture is now parented by CCameraHandler that might cause the problems. At the moment I am not so sure if it is a good Idea to use a SmartPointer in this case. Any Ideas what might cause this error on destruction?
Edit:
The CCameraHandler dtor looks like this (threads should be deleted before the worker):
CCameraHandler::~CCameraHandler(void)
{
//Stop grabbing and processing
emit stopGrabbing();
emit stopProcessing();
/*Wait for the capture thread to terminate. The destructor of CCamera Handler might be called on application close. Therefore it is important to wait for QThreads to terminate. Else the application might close before threads get deleted*/
m_CameraCaptureThread->exit();
m_CameraCaptureThread->wait();
//Wait for the processing thread to terminate
m_ProcessingThread->exit();
m_CameraCaptureThread->wait();
qDebug() << "CCameraHandler deleted";
}
An object that has been moved to another thread must be destructed either:
From the thread itself, or
From any thread after the thread itself has been destructed.
Caveat: QThread is not safe to be destructed before you stop it. To do that safely to a thread that merely runs an event loop, you should use the following subclass instead:
class Thread : public QThread {
using QThread::run; // final
public:
Thread(QObject * parent = 0) : QThread(parent) {}
~Thread() { quit(); wait(); }
};
Given such a class, destructed from the GUI thread, you simply need to destruct it before you destruct any objects that were moved to the thread. Of course, it's not necessary to hold such objects as pointers at all, but the code below will work whether you hold them directly or as pointers.
class Foo : public Bar {
CCameraCapture m_CameraCapture;
CImageProcessor m_ImageProcessor;
Thread m_CameraCaptureThread;
Thread m_ProcessingThread;
...
}
When the class is destructed, the following happens, in order:
~Foo() body runs (it may be empty).
Members in the ... section, if any, are destructed in reverse order of declaration.
m_ProcessingThread.~Thread runs, followed by superclass destructors (~QThread, and finally ~QObject). Any objects that were moved to that thread are now threadless.
m_CameraCaptureThread.~Thread runs, followed by superclass destructors. Any objects that were moved to that thread are now threadless.
m_ImageProcessor destructors run. As a threadless object, the destruction is safe from any thread.
m_CameraCapture destructors run. As a threadless object, the destruction is safe from any thread.
If you used QScopedPointer<...> to hold those instances, things would be exactly the same, just that every object's destruction would be wrapped in the body of ~QScopedPointer<...>.
Note that the use of even a raw pointer to hold those instances is a premature pessimization: you waste a bit of heap, and access to the instances is a bit slower due to an extra layer of indirection. Those things in isolation may not play a big role, but if there are thousands of objects all coded that way, things can add up.
Don't allocate class members in individual heap blocks unless absolutely necessary.
Problem is that you are doing some UI stuff from none UI thread.
It is hard to tell exactly where is the problem since you didn't give information what exacly CCameraCapture do.
I suspect that after capturing a frame you are setting a pixmap on label (to show frame) instead emit a signal with new frame and connect this signal with respective slot of UI element. So I think that scoped pointer and signal and slots have nothing to do with your problem, problem is that you didn't use signal slot mechanism in place where it was required.
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)
When a QObject-derived object is being destructed, is it OK to emit a signal from its destructor? I tried it and it seems to work, but I'm not sure if it should be done.
For example, this code
class MyClass : public QObject {
signals:
void mySignal(const QString &str);
public:
QString myString;
~MyClass() { emit mySignal(myString); }
}
would pass a const reference to an object that might be out of scope by the time when the connected slot is executed.
Emission is generally fine (QObject does it too with the "destroyed" signal), including a case as yours. When the connection is direct, the string is still alive. And when it is QueuedConnection, then the string is first copied to the event loop.
If you ask is it OK: Yes, it will not cause any problem in itself.
If you would ask if its a generally safe thing to do in Qt? Definitely not safe. You have to be very mindful what you do if you emit from destructor, and have a good understanding of the Qt event system.
Remember that when a QObject descendant destructs, it disconnects all signals, so the destructed object does not get any more calls on their slots? Well there is a catch: destruction order. The QObject destructor does that disconnect, and it is the LAST to destruct, meaning, in the destruction chain events might still arrive to the "half-dead" object, causing access violations when accessing virtual functions and members of already destructed descendants. The possibility is present if you use the event system, and any of these conditions are met:
In multi threaded environment, if the object is not destructed on its own thread.
In multi threaded environment, if the object's destruction chain triggers the run of a processEvents() on any run path.
In multi threaded environment, if any object on another thread has a direct connection to this object, and it fails to react to its destroyed signal in direct connection.
In single threaded environment, when the destructors sends signals
that might return to the object in a direct connect chain.
I call this effect "life during death", and emiting signals or running any form of processEvents() (typically accidentally) in the destructor increase the chance to create such an error.
Of course, if you can somehow guarantee that not any present or future code will actually trigger any slots during destruction, its perfectly safe to emit from destructor, but its very hard to give such guarantee, and I'd advice simply avoid it whenever possible.
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.
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.