Случайные сбои приложения Qt при использовании обратных вызовов и отправке сигналов из std :: thread или boost :: thread - PullRequest
0 голосов
/ 13 октября 2018

У меня раздражающая проблема с 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;   
}

Вот здесь и начинается проблема.При обратном вызове в моем QDialog класса B я излучаю сигнал Qt

void myClassB::mycallback(std::string txt)
{
   emit sig_qt_data_received(txt);   
}

Этот сигнал подключается в конструкторе моего класса B:

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, он будетработать без сбоев , но иногда весь пользовательский интерфейс зависает (Редактировать: это неверно, см. мой ответ ).

Я надеюсь, что кто-то может помочь.Если вам нужно больше кода / реального кода, дайте мне знать, я напишу фактический исполняемый код, который вы можете запускать и компилировать, но основы те же, вот как работает код.

Я не хочуиспользовать QThread.

1 Ответ

0 голосов
/ 13 октября 2018

Решено!Qt::DirectConnection был виновником, теперь я использую Qt::AutoConnection, и он никогда не падает, и согласно документам это по умолчанию:

(по умолчанию) Если получатель живет в потоке, который излучает сигнал, Qt :: DirectConnection используется.В противном случае используется Qt :: QueuedConnection.Тип соединения определяется при подаче сигнала.

Ответ GM, приведенный выше, дал мне подсказку (спасибо):

тот факт, что явно указывается тип соединения в виде Qt:: DirectConnection меняет поведение и предполагает, что вы почти наверняка получили состояние гонки из-за многопоточности

Также спасибо jpo38 за предложение / ответ в любом случае.

Теперь я знаю, что иногда говорилон замерзнет, ​​но нет, это неправильно , он никогда не замерзнет, ​​я перепутал вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...