C++ Qt应用程序通过使用回调并从std::thread或boost::thread发出信号而随机崩溃

C++ Qt应用程序通过使用回调并从std::thread或boost::thread发出信号而随机崩溃,c++,qt,C++,Qt,我对Qt和多线程有一个恼人的问题。下面我创建了一些简化的代码。在我的真实代码中,原理是完全相同的,但过于复杂,因此无法使用简化版本 问题在于,应用程序在运行时的不同时间点随机崩溃,并显示不同的消息: free(): invalid pointer double free or corruption 崩溃是从Qt内部触发的,我将在文章末尾解释 下面是代码的工作原理 因此,我有一个classA,它启动了一个线程: class classA { public: void

我对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
}
myClassB的构造函数中,我将回调分配给
boost::function
,如下所示(如我所说,回调工作正常)

问题就从这里开始。在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\u 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。 连接类型在发出信号时确定

G.M.上面的回答给了我一个提示(谢谢):

将连接类型显式指定为 DirectConnection改变了行为,表明您几乎 由于线程问题,当然有一个竞速条件

同样感谢jpo38的建议/回复


现在我知道我说有时它会冻结,但不,这是不正确的,它从不冻结,我把事情搞糊涂了。

解决了
Qt::DirectConnection
是罪魁祸首,现在我使用
Qt::AutoConnection
,它从不崩溃,根据文档,它是默认的:

(默认)如果接收器位于发出信号的线程中, 使用Qt::DirectConnection。否则,将使用Qt::QueuedConnection。 连接类型在发出信号时确定

G.M.上面的回答给了我一个提示(谢谢):

将连接类型显式指定为 DirectConnection改变了行为,表明您几乎 由于线程问题,当然有一个竞速条件

同样感谢jpo38的建议/回复


现在我知道我说过有时它会冻结,但不,这是不正确的,,它从不冻结,我把事情弄糊涂了。

你的问题中缺少很多代码/上下文,但是。。。将连接类型显式指定为
Qt::DirectConnection
会改变行为,这一事实表明,由于线程,您几乎肯定会遇到竞争条件。另外,请注意,不需要使用
new
分配
boost::thread
,因为它是移动可构造/可分配的.G.M,如果您发布答案,我将接受您的答案。您的问题中缺少很多代码/上下文,但是。。。将连接类型显式指定为
Qt::DirectConnection
会改变行为,这一事实表明,由于线程,您几乎肯定会遇到竞争条件。另外,请注意,不需要使用
new
分配
boost::thread
,因为它是move-constructible/assignable.G.M,如果您发布答案,我将接受您的答案。
connect(this, SIGNAL(sig_qt_data_received(std::string)), this, SLOT(data_received(std::string)), Qt::DirectConnection);
void myclassB::data_received(std::string txt)
{
    ui->lbl_status->setText(txt);
}
free(): invalid pointer
double free or corruption