Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-49679

Multithread signal/slot memory leak in ubuntu

    XMLWordPrintable

Details

    • Bug
    • Resolution: Invalid
    • P3: Somewhat important
    • None
    • 5.5.1
    • None
    • ubuntu 14.04LTS

    Description

      Memory leak after emitting queued signal with a constant reference parameter form a qobject from another thread.

      This is my post at stackoverflow: http://stackoverflow.com/questions/33956972/memory-leak-in-qt-emitting-const-container

      typedef QList<long double> doubleList;
      
      class MyThread : public QThread
      {
      public:
          MyThread();
          ~MyThread();
      };
      
      class MyObject : public QObject
      {
          Q_OBJECT
      public:
          explicit MyObject(QObject *parent = 0);
          ~MyObject();
      
      signals:
          void jobDone(const doubleList&);
      
      public slots:
          void jobStart();
      };
      
      namespace Ui {
      class MainWindow;
      }
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          explicit MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      private:
          Ui::MainWindow *ui;
      
      private slots:
          void buttonClicked();
          void receiveResult(const doubleList&);
      };
      
      MainWindow::MainWindow(QWidget *parent) :
          QMainWindow(parent),
          ui(new Ui::MainWindow)
      {
          ui->setupUi(this);
          qDebug() << "GUI Thread ID: " << QThread::currentThreadId();
          connect(ui->pushButton, &QPushButton::clicked, this, &MainWindow::buttonClicked);
      
          qRegisterMetaType<doubleList>("doubleList");
      }
      
      MainWindow::~MainWindow()
      {
          delete ui;
      }
      
      void MainWindow::buttonClicked()
      {
          MyThread* thread = new MyThread;
          MyObject* object = new MyObject;
      
          object->moveToThread(thread);
      
          connect(thread, &MyThread::started, object, &MyObject::jobStart);
          connect(object, &MyObject::jobDone, this, &MainWindow::receiveResult);
          connect(object, &MyObject::jobDone, thread, &MyThread::quit);
          connect(thread, &MyThread::finished, object, &MyObject::deleteLater);
          connect(thread, &MyThread::finished, thread, &MyThread::deleteLater);
          thread->start();
      }
      
      void MainWindow::receiveResult(const doubleList &)
      {
          qDebug() << "Received result";
      }
      
      MyThread::MyThread()
      {
          qDebug() << "MyThread ctor, thread ID:\t" << currentThreadId();
      }
      
      MyThread::~MyThread()
      {
          qDebug() << "MyThread dtor, thread ID:\t" << currentThreadId();
      }
      
      MyObject::MyObject(QObject *parent) : QObject(parent)
      {
          qDebug() << "MyObject ctor. MyObject pointer:\t" << this
                      << "\tThread ID:\t" << QThread::currentThreadId();
          qRegisterMetaType<doubleList>("doubleList");
      }
      
      MyObject::~MyObject()
      {
          qDebug() << "MyObject dtor and list deleted. MyObject pointer:\t" << this
                   << "\tThread ID:\t" << QThread::currentThreadId();
      }
      
      void MyObject::jobStart()
      {
          doubleList list;
          qDebug() << this << "jobStart() called. Thread ID:\t" << QThread::currentThreadId();
          for (int i = 0; i != 100000000; ++i)
          {
              list.push_back(i);
          }
      
          emit jobDone(list);
      }
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          MainWindow w;
          w.show();
      
          return a.exec();
      }
      
      MyThread ctor, thread ID:    0x7f3dbbbf1780
      MyObject ctor. MyObject pointer:     MyObject(0xbc03a0)     Thread ID:   0x7f3dbbbf1780
      MyObject(0xbc03a0) jobStart() called. Thread ID:     0x7f3d9e6df700
      Received result
      MyObject dtor and list deleted. MyObject pointer:    MyObject(0xbc03a0)     Thread ID:   0x7f3d9e6df700
      MyThread dtor, thread ID:    0x7f3dbbbf1780
      MyThread ctor, thread ID:    0x7f3dbbbf1780
      MyObject ctor. MyObject pointer:     MyObject(0xbafca0)     Thread ID:   0x7f3dbbbf1780
      MyObject(0xbafca0) jobStart() called. Thread ID:     0x7f3d9e6df700
      Received result
      MyObject dtor and list deleted. MyObject pointer:    MyObject(0xbafca0)     Thread ID:   0x7f3d9e6df700
      MyThread dtor, thread ID:    0x7f3dbbbf1780
      MyThread ctor, thread ID:    0x7f3dbbbf1780
      MyObject ctor. MyObject pointer:     MyObject(0xbc03a0)     Thread ID:   0x7f3dbbbf1780
      MyObject(0xbc03a0) jobStart() called. Thread ID:     0x7f3d9e6df700
      Received result
      MyObject dtor and list deleted. MyObject pointer:    MyObject(0xbc03a0)     Thread ID:   0x7f3d9e6df700
      MyThread dtor, thread ID:    0x7f3dbbbf1780
      

      Attachments

        1. main.cpp
          0.2 kB
        2. mainwindow.cpp
          1 kB
        3. mainwindow.h
          0.5 kB
        4. mainwindow.ui
          1 kB
        5. myobject.cpp
          0.7 kB
        6. myobject.h
          0.4 kB
        7. mythread.cpp
          0.3 kB
        8. mythread.h
          0.2 kB
        9. QThreadMemoryLeak.pro
          0.4 kB
        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            thiago Thiago Macieira
            tomhk215 tomhk215
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes