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