简体   繁体   中英

Memory leak when using QThread and QPrinter

I'm using QThread for printing work via QPrinter

My PrintWorker look like this :

class PrintWorker : public QObject {
    Q_OBJECT

public:
    PrintWorker(QThread*, QPrinter*, QPicture*, QPainter*, QObject *parent = 0);

private:
    QPicture *_picture = nullptr;
    QPrinter *_printer = nullptr;
    QPainter *_painter = nullptr;

    public slots:
    void print();

signals:
    void done();
};

PrintWorker::PrintWorker(QThread *thread, QPrinter *printer, QPicture *picture, QPainter *painter, QObject *parent) :QObject(parent),
_picture(picture), _printer(printer), _painter(painter)
{
    moveToThread(thread);
    QObject::connect(thread, &QThread::started, this, &PrintWorker::print);
    QObject::connect(this, &PrintWorker::done, thread, &QThread::quit);
    QObject::connect(this, &PrintWorker::done, this, &PrintWorker::deleteLater);
    QObject::connect(thread, &QThread::finished, thread, &QThread::deleteLater);
}

void PrintWorker::print() {
    // do some print job with painter and picture
    emit done();
}

And print Method is this :

void NewService::print() {
    if (!_printer) { /* _printer : a private member */
        _printer = new QPrinter(QPrinter::HighResolution);
        _printer->setPageSize(QPrinter::A5);
        _printer->setPageOrientation(QPageLayout::Portrait);
        _printer->setColorMode(QPrinter::Color);
    }

    if (!_printDialog) { /* _printDialog : a private member */
        _printDialog = new QPrintDialog(_printer);
    }

    if (_printDialog->exec() == QPrintDialog::Accepted) {
        MyWidget *widget = new MyWidget(/* some args*/);

        QPainter *painter = new QPainter;
        QPicture *picture = new QPicture;
        widget->render(picture);

        QThread *thread = new QThread;
        PrintWorker *worker = new PrintWorker(thread, _printer, picture, painter);
        thread->start();
    }
}

Now before invoking print() my app exposes about 9MB of memory after printing and invoking PrintWorker::print() my app's memory usage get to 26MB

In Another world if we remove emit done at last part in PrintWorker::print() it makes no difference.

What we expect after finishing job is memory usage should get down to 26MB - Thread space + _printer + _printDialog objects size ≈ 14MB

So What's wrong with this ?

You are deleting PrintWorker and QThread objects, but not QPainter , QPicture , MyWidget , QPrintDialog nor QPrinter . Those are memory leaks ( new with no delete ). Note that PrintWorker destructor could take care of deleting QPainter , QPicture and QPrinter , additionnaly, it could also take ownership of MyWidget and delete it. Hopefully QPrintDialog object is deleted by NewService class, but it's hard to say as code was not posted.

Also, as recommende by rafael gonzalez, you should check that QThread PrintWorker and QThread are actually being deleted.

By the way, how did you check memory usage? Through a leak detection tool (like valgrind, VLD...)? Or through Windows Task Manager. Because task manager is definitely unaccurate.

By calling QThread::quit() you are activly exiting the EventLoop in this thread. A QObject::deleteLater() for objects residing in this thread may not be executed anymore (though they mention on QThread::finished() -signal the delete later slot will still be called).

I personally would just set up the connection using the finished() signal or set the parent of the worker-object to be the thread itself, then Qt actually has to remove the object.

http://doc.qt.io/qt-5/qthread.html#exit

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