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

标签 c++ qt

我对 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/

相关文章:

c++ - CUDA : stencil code not working

c++ - OpenCV CV::Mat 和 Eigen::Matrix

c++ - Qt 安全删除设备

multithreading - PyQt:如何将停止信号发送到对象正在运行有条件的 while 循环的线程?

c++ - 如何很好地将 "cast"qint64 转换为 QProgressBar 的 int

c++ - 声明一个新节点但不等于 NULL

c++ - Boost图库分布式广度优​​先搜索MPI_Unpack运行时报错

c++ - 具有 FIONREAD 返回值的 ioctl

c++ - 如何判断何时在 QButtonGroup 中单击 QPushButton

c++ - Qt中的内存管理?