我对 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,而在于 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
它永远不会崩溃,根据文档,它是默认设置:
(Default) If the receiver lives in the thread that emits the signal, Qt::DirectConnection is used. Otherwise, Qt::QueuedConnection is used. The connection type is determined when the signal is emitted.
G.M 上面的回复给了我提示(感谢):
the fact that explicitly specifying the connection type as Qt::DirectConnection changes the behaviour suggests you've almost certainly got a race condition due to threading
也感谢 jpo38 的建议/回复。
现在我知道我说有时它会卡住,但不,那是不正确的,它永远不会卡住,我把事情弄糊涂了。
关于c++ - Qt 应用程序随机崩溃通过使用回调和从 std::thread 或 boost::thread 发出信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52790208/