簡體   English   中英

在傳遞的對象被銷毀之前發送信號傳遞QObject指針作為參數是否安全?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM