[英]Is it safe to emit signal passing QObject pointer as parameter right before the passed object is going to be destroyed?
讓我們考慮這個簡單的例子:
Class Emitter: public QObject {
...
signal:
surfaceDestroyed(QObject*);
public:
void emittingMethod(QObject* surface) {
emit surfaceDestroyed(surface);
delete surface;
}
}
我有這種情況的排隊連接
connect(emitterObject, SIGNAL(surfaceDestroyed(QObject*), receiverObject,
SLOT(onSurfaceDestroyed(QObject*)), Qt::QueuedConnection);
在onSurfaceDestroyed方法中,取消引用並使用接收到的QObject
那么問題是這段代碼的安全性如何? 我在QT網站上已經閱讀了很多相關信息,但我仍然沒有清楚地了解這個問題。
在我看來,這個代碼是不安全的,因為一旦處理了事件循環並且接收器對象訪問釋放的內存,就會發送信號,然后表面被破壞,而不是事件發生在receiverObject上,因此SIGSEGV
這是真實代碼的簡化示例,因此很難跟蹤崩潰是否會因此而發生。
這取決於信號槽連接的類型。 如果發送方和接收方屬於同一個線程,則默認情況下連接是直接的。 在這種情況下,當您發出信號時,將立即調用插槽。 信號功能完成后,您可以確定插槽已完成。
當發送方和接收方屬於不同的線程時,默認情況下連接排隊 。 在這種情況下,您的代碼不安全。 可以在調用信號之前調用插槽。 即使deleteLater
也不會保存這種情況,因為它由發送者的線程的事件循環處理,並且不依賴於其他線程的事件循環。
因此,如果要編寫此類代碼,請確保對象位於同一個線程中。 您可以通過Qt::DirectConnection
選項connect
函數以使連接類型更清晰。
如果要使用排隊連接,可以在發送aboutToBeDeleted
發出例如aboutToBeDeleted
信號。 接收器將接收該信號,以某種方式處理它並使用cleanUpCompleted
信號進行響應, cleanUpCompleted
信號將觸發實際的對象刪除。
還要考慮使用標准的QObject::destroyed
信號。 它在對象被銷毀之前立即調用,但在許多情況下可能很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.