簡體   English   中英

QThread正在創建內存泄漏

[英]QThread is creating a memory leak

經過大量測試並更改了我的QT應用程序后,Visual Leak Detector識別出了令人討厭的泄漏源(8個字節)。 VLD報告說,除QThread*指針外,QT應用程序是干凈的。

一些實施背景:Jeffrey Holmes將應用程序建模為解決方案的混合體, 使用Qt批量下載網頁 感謝Jeffrey提早提供解決方案!

問題:

  • 為什么工作線程完成工作后QThread*不會自我破壞?

  • 工作完成后,如何強制QThread*刪除線程和輔助對象?

  • QThread應該以不同的方式實現嗎?

碼:

void vqMDIChildDialog::processWorkQueue(bool bIsBC)
{

if (m_listOfTables.isEmpty() && currentReplicationThreads == 0)
{
}
else if (!m_listOfTables.isEmpty())
{
    for (int i = 0; i < maxReplicationThreads && !m_listOfTables.isEmpty();i++)
    {
        QThread *thread = new QThread;
        QPointer<vcSharedDataQt> worker = new vcSharedDataQt();
        worker->moveToThread(thread);
        QString tmpTableName (m_listOfTables.dequeue());
        worker->setParentObject(this);
        //   
        // set properties on the worker object.
        //  
        connect(thread,  SIGNAL(started()),  worker, SLOT(process()));
        connect(worker,  SIGNAL(finished()), thread, SLOT(quit()));
        connect(worker,  SIGNAL(finished()), worker, SLOT(deleteLater()));
        connect(thread,  SIGNAL(finished()), thread,SLOT(deleteLater()));

        connect(worker,
            SIGNAL(updateMessageFromThread(  const QString&,
                             const QString&,
                             const QString&,
                             const QString&,
                             const QString&,
                             const QString&,
                             const QString&)), 

            this,
            SLOT(UpdateStatusBarFromThread( const QString&,
                            const QString&,
                            const QString&,
                            const QString&,
                            const QString&,
                            const QString&,
                            const QString&)));

        thread->setObjectName(worker->getUniqueKey());

        thread->start();
        currentReplicationThreads ++;
    }
}

}

Stack不允許我回答這個問題,所以:

該功能受QMutex保護:

mutex.lock();
processWorkQueue();
mutex.unlock();

這導致內存泄漏。 QThread顯然無法在輔助線程完成時銷毀。 我刪除了互斥鎖,並且VLD報告QThread沒有內存泄漏。

  1. QThread並不真正知道何時完成工作。 您可以通過考慮如何實現此問題來回答自己的問題。

    它的run()方法只是旋轉事件循環。 由於所有事件循環都可以知道是否有任何事件發布到其上,因此,您可以合理地實現的唯一條件是,在沒有其他事件發生時退出線程。 這將使線程立即退出,因此根本沒有幫助。

    也許您希望在沒有更多以該線程為線程的QObject時終止該線程。 當然可以在QThread中將其實現為可選行為,但是我不知道這是否會被接受。 它一定不是默認行為,因為在許多情況下,不斷銷毀和重新創建線程簡直是浪費的-人們可能想保留一個沒有對象的線程。

    最終只有您知道線程的工作時間。 您的工作程序對象可以調用thead()->quit()或完成后發出信號-就像您已經做過的那樣。

  2. 由於線程是可重新啟動的,因此在完成工作后, QThread無法銷毀自己。 您可以完全控制線程的生存期,因此您可以肯定地在線程工作完成后銷毀它,而您已經這樣做了,只有錯了。

  3. 您的問題實際上是您希望事情發生的順序。 deleteLater操作由事件循環執行。 如果線程的事件循環未運行,則deleteLater是NO-OP。

    因此,首先,應進行連接,以使它們形成只能以明確定義的順序執行的級聯:

     connect(thread, SIGNAL(started()), worker, SLOT(process())); connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater())); connect(worker, SIGNAL(destroyed()), thread, SLOT(quit())); connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater())); 

    然后,您必須確保運行processWorkQueue方法的線程未被阻塞,並且有機會繼續事件循環。 這個事件循環將處理線程的刪除。

    正如AlexP所指出的那樣,這在Qt 4.7或更早的版本中不起作用,因為所有這些版本在QThread的實現中均存在錯誤。 “ QThread的行為已更改”是委婉說法,因為“有一個丑陋的錯誤終於解決了”。

  4. 您的連接過於冗長。 您可以從簽名中刪除空格和引用/ const-reference。 如果是this則第三個參數也是可選的。 它應該看起來像:

     connect(worker, SIGNAL(updateMessageFromThread(QString,QString,QString,QString, QString,QString,QString)), SLOT(updateStatusBarFromThread(QString,QString,QString,QString, QString,QString,QString))); 

答案:

  • 為什么工作線程完成工作后QThread*不會自我破壞?

因為有多種使用QThread ,其中在工作人員完成后至少必須有一種能夠查詢線程狀態或類成員的方法。 此外,線程可能會重新啟動。

  • 工作完成后,如何強制QThread*刪除線程和輔助對象?

finished信號應該足以讓您調用刪除兩者的插槽。

  • QThread應該以不同的方式實現嗎?

針對不同情況有不同的實現。 http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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