簡體   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