繁体   English   中英

使用QThread和QPrinter时发生内存泄漏

[英]Memory leak when using QThread and QPrinter

我正在使用QThread通过QPrinter进行打印工作

我的PrintWorker看起来像这样:

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();
}

print方法是这样的:

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();
    }
}

现在,在调用print()之前,我的应用在打印并调用PrintWorker::print()之后会暴露大约9MB的内存,我的应用的内存使用量达到26MB

在另一个世界中,如果我们删除最后在PrintWorker::print() emit done ,则没有任何区别。

完成工作后,我们期望的是内存使用量应降至_printer线程空间+ _printer + _printDialog对象的大小_printDialog

那么,这怎么了?

您将删除PrintWorkerQThread对象,但不会删除QPainterQPictureMyWidgetQPrintDialogQPrinter 这些是内存泄漏(没有delete new泄漏)。 请注意, PrintWorker析构函数可以负责删除QPainterQPictureQPrinter ,此外,它还可以拥有MyWidget所有权并将其删除。 希望QPrintDialog对象被NewService类删除,但是很难说,因为没有发布代码。

另外,按照拉斐尔·冈萨雷斯( PrintWorker gonzalez)的建议,您应检查QThread PrintWorkerQThread是否已真正删除。

顺便问一下,您如何检查内存使用情况? 通过泄漏检测工具(如valgrind,VLD ...)? 或通过Windows任务管理器。 因为任务管理器绝对不准确。

通过调用QThread::quit()您可以在该线程中主动退出EventLoop。 驻留在该线程中的对象的QObject::deleteLater()可能不再执行(尽管它们在QThread::finished() - QObject::deleteLater()提到,以后删除槽仍将被调用)。

我个人只是使​​用finished()信号来建立连接,或者将worker对象的父对象设置为线程本身,然后Qt实际上必须删除该对象。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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