简体   繁体   中英

QThread Memory Leak

main.cpp:

#include <QCoreApplication>
#include <QtCore>
#include "myobject.h"

QThread* cThread;
MyObject* cObject;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    cThread = new QThread();
    cObject = new MyObject();
    cObject->moveToThread(cThread);

    QObject::connect(cThread, SIGNAL(started()),
                     cObject, SLOT(doWork()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cThread, SLOT(deleteLater()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cObject, SLOT(deleteLater()));

    cThread->start();

    return a.exec();
}

myobject.cpp:

#include "myobject.h"

MyObject::MyObject(QObject *parent) :
    QObject(parent)
{
}

void MyObject::doWork()
{
    qDebug() << "Hi";
    QThread::currentThread()->quit();
    return;
}

myobject.h:

#ifndef MYOBJECT_H
#define MYOBJECT_H

#include <QtCore>

class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = 0);

signals:

public slots:
    void doWork();

};

#endif // MYOBJECT_H

Apparently, according to: https://stackoverflow.com/a/16062717 , there is a memory leak, but how do I fix it? I guess I would have to return to the event loop and then call quit? But the issue is that I don't have access to the event loop.

There isn't a memory leak. Qt does clean up properly if you stick to its object model , and object trees and ownership . I also like following the documented examples .

Here is the example you referenced, with observation added on deleteLater() .

main.cpp

#include <QCoreApplication>
#include <QtCore>
#include <QThread>

class MyThread : public QThread
{
    Q_OBJECT
public slots:
    void deleteLater()
    {
        qDebug() << Q_FUNC_INFO;
        QThread::deleteLater();
    }
};


class MyObject : public QObject
{
    Q_OBJECT
public:
    explicit MyObject(QObject *parent = 0){}

signals:

public slots:
    void deleteLater()
    {
        qDebug() << Q_FUNC_INFO;
        QObject::deleteLater();
    }

    void doWork()
    {
        qDebug() << "Hi";
        QThread::currentThread()->quit(); // It is supposed to stop here, but it doesn't.
        return;
        for (int i = 0; i < 1000000; i++) {
            qDebug() << i;
        }
    }

};

QThread* cThread;
MyObject* cObject;

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    cThread = new MyThread();
    cObject = new MyObject();
    cObject->moveToThread(cThread);

    QObject::connect(cThread, SIGNAL(started()),
                     cObject, SLOT(doWork()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cThread, SLOT(deleteLater()));

    QObject::connect(cThread, SIGNAL(finished()),
                     cObject, SLOT(deleteLater()));

    cThread->start();

    return a.exec();
}

output:

Hi
void __thiscall MyObject::deleteLater(void)
void __thiscall MyThread::deleteLater(void)

Hope that helps.

I am the poster on the link. There is in fact no memory leak with the default connection. By subclassing deleteLater and destructors like @phyatt did you obtain :

Hi 
void MyObject::deleteLater() 
virtual MyObject::~MyObject()  Being deleted 
void MyThread::deleteLater() 
virtual MyThread::~MyThread()  Being deleted 

But If you use Qt::QueueConnection for instance in your connections you obtain:

Hi 
void MyThread::deleteLater() 
virtual MyThread::~MyThread()  Being deleted 

And the object cObject is leaked.

It is undocumented when the thread will effectively exit. So I cannot argue whether this behavior will always be the same. One possibility is to make the thread launcher responsible for doing the cleanup work. For instance:

 void cleanup(){
  cThread->exit();
  cThread->wait();
  delete cThread;
  delete cObject;
 }

To wrap things up, you don't have to fix anything with this code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM