问题
Lets consider this simple example:
Class Emitter: public QObject {
...
signal:
surfaceDestroyed(QObject*);
public:
void emittingMethod(QObject* surface) {
emit surfaceDestroyed(surface);
delete surface;
}
}
I have a queued connection for this case
connect(emitterObject, SIGNAL(surfaceDestroyed(QObject*), receiverObject,
SLOT(onSurfaceDestroyed(QObject*)), Qt::QueuedConnection);
In onSurfaceDestroyed method the received QObject is dereferenced and used
So the question is how safe this code is? I've read pretty much info on that on QT site and here, but I still don't have a clear understanding of the problem.
In my opinion this code is not safe, as a signal can be sent, then surface destroyed, than when an event comes for receiverObject once the event loop is processed and receiver object accesses released memory, thus SIGSEGV
This is a simplified example of real code, so it's hard to track if crashes can happen because of that.
回答1:
It depends on the type of the signal-slot connection. Connections are direct by default if the sender and the receiver belong to the same thread. In this case the slot will be called immediately when you emit the signal. When the signal function is finished, you can be sure that the slot has also finished.
When the sender and the receiver belong to different threads, the connection is queued by default. In this case your code is not safe. The slot can be called much later than the signal was called. Even deleteLater
will not save the situation because it's processed by the sender's thread's event loop and doesn't depend on the other thread's event loop.
So if you want to write such code, ensure that your objects are in the same thread. You can pass Qt::DirectConnection
option to connect
function to make connection type more clear.
If you want to use queued connection, you can emit e.g. aboutToBeDeleted
signal in the sender. The receiver will receive that signal, process it somehow and respond with cleanUpCompleted
signal that will trigger the actual object deletion.
Also consider using standard QObject::destroyed
signal. It's called immediately before the object is destroyed but can be useful in many cases.
来源:https://stackoverflow.com/questions/20376571/is-it-safe-to-emit-signal-passing-qobject-pointer-as-parameter-right-before-the