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