簡體   English   中英

通過使用回調並從std :: thread或boost :: thread發出信號,Qt應用程序隨機崩潰

[英]Qt Application Random Crashes via using callbacks and emitting signals from std::thread or boost::thread

我對Qt和多線程有一個煩人的問題。 下面,我創建了一些簡化的代碼。 在我的真實代碼中,原理是完全相同的,但是過於復雜,因此使用簡化版本。

問題在於,應用程序在運行時的不同時間點隨機崩潰,並顯示不同的消息:

free(): invalid pointer
double free or corruption

崩潰是從Qt內部觸發的,我將在文章末尾進行解釋。

代碼是這樣工作的。

因此,我有一個啟動線程的classA

class classA
{
   public:

      void                                   start();
      boost::function<void (std::string)>    __ptr; // for callback

   private:

      boost::thread  *                    thread;
      void                                run();
};

void classA:start()
{ 
   thread = new boost::thread(&classA::run, this); // start the thread
}

這是在單獨線程中運行的實際方法:

void classA::run()
{
   for (int i = 0; i < 50000; i++)
   {
      static int count = 0;

      __ptr("test123" + std::to_string(++count));
   }
}

在我的QDialog繼承的類中,我有一個簡單的方法來分配boot::function因此我聲明了另一個boost::function ptr。 問題不在於ptr,而是Qt,請繼續閱讀,回叫工作得很好...

class myClassB : public QDialog
{
   Q_OBJECT

   public:

      explicit myClassB (QWidget *parent);
      classA   ca;

   private:

      boost::function<void (std::string)>    __ptr;

      void mycallback(std::string);   
};

myClassB的構造函數中,我將分配回叫給boost::function這樣的代碼(就像我說的那樣,回調工作正常)。

myClassB::myClassB()
{
   this->__ptr    = ( boost::bind( &myClassB::mycallback, this, _1 ) );
   ca.__ptr       = __ptr;   
}

這是問題開始的地方。 在我的classB QDialog中的回調中,我發出一個Qt信號

void myClassB::mycallback(std::string txt)
{
   emit sig_qt_data_received(txt);   
}

這個信號被連接到我的classB的構造函數中:

connect(this, SIGNAL(sig_qt_data_received(std::string)), this, SLOT(data_received(std::string)), Qt::DirectConnection);

最后是Qt插槽的實現:

void myclassB::data_received(std::string txt)
{
    ui->lbl_status->setText(txt);
}

這是問題所在:

如果刪除 ui->lbl_status->setText(txt); ,程序可以完美運行,永遠不會崩潰,如果離開它,它會隨機崩潰:

free(): invalid pointer
double free or corruption

看來,這個問題是內Qt的,當我刪除的setText()引用,它不會崩潰,我都遵循幾乎每個GUI多線程程序,我發現,我不知道我做錯了。

要連接Qt信號,我正在使用Qt::DirectConnection ,如果我使用Qt::AutoConnection ,它將正常工作而不會崩潰, 但有時整個UI會凍結 (編輯: 這是不正確的,請參見我的回答 )。

我希望有人能幫幫忙。 如果您需要更多代碼/真實代碼,請告訴我,我將編寫一個可以運行和編譯的實際可運行代碼,但基本原理相同,這就是代碼的工作方式。

我不想使用QThread。

解決! Qt::DirectConnection是罪魁禍首,現在我使用Qt::AutoConnection ,它從不會崩潰,根據文檔,它是默認值:

(默認)如果接收器位於發出信號的線程中,則使用Qt :: DirectConnection。 否則,將使用Qt :: QueuedConnection。 發出信號時確定連接類型。

通用汽車上述回應給了我提示(謝謝):

將連接類型顯式指定為Qt :: DirectConnection會改變行為,這一事實表明您幾乎可以肯定由於線程原因而出現了競爭情況

同樣感謝jpo38的建議/回復。

現在我知道我說過有時候它會凍結,但是不, 那是不對的 ,它永遠不會凍結,我有些困惑。

暫無
暫無

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

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