Is it safe to emit signal passing QObject pointer as parameter right before the passed object is going to be destroyed?

懵懂的女人 提交于 2020-12-08 16:10:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!