Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/147.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用QThread和QPrinter时内存泄漏_C++_Qt_Memory Leaks_Qt5_Qprinter - Fatal编程技术网

C++ 使用QThread和QPrinter时内存泄漏

C++ 使用QThread和QPrinter时内存泄漏,c++,qt,memory-leaks,qt5,qprinter,C++,Qt,Memory Leaks,Qt5,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 =

我正在使用
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
,则没有什么区别

完成作业后,我们希望内存使用量降至26MB-线程空间+
\u打印机
+
\u打印对话框
对象大小≈ 14MB


那么这又有什么问题呢?

您正在删除
PrintWorker
QThread
对象,但不是
qPaint
QPicture
MyWidget
QPrintDialog
QPrinter
。这些是内存泄漏(
new
,没有
delete
)。请注意,
PrintWorker
析构函数可以负责删除
QPainter
QPicture
QPrinter
,此外,它还可以拥有
MyWidget
并删除它。希望
QPrintDialog
对象被
NewService
类删除,但很难说,因为代码没有发布

此外,根据rafael gonzalez的建议,您应该检查
QThread
PrintWorker
QThread
是否实际被删除


顺便问一下,你是如何检查内存使用情况的?通过泄漏检测工具(如valgrind、VLD…)?或通过Windows任务管理器。因为任务管理器肯定是不可靠的。

通过调用
QThread::quit()
您正在主动退出此线程中的EventLoop。驻留在此线程中的对象的
QObject::deleteLater()
可能不再执行(尽管它们在
QThread::finished()
-上提到,仍将调用delete later插槽)

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


您是否尝试添加qDebug查看是否调用了打印工作人员的析构函数?@rafaelgonzalez.Yes
PrintWorker::~PrintWorker()
被调用。是的,测量工具是Windows任务管理器,也是的PrintWorker::~PrintWorker()调用,但我没有得到它,我将线程对象设为私有,并设置
QObject::connect(_printThread,&QThread::destromed,this,&NewService::onPrintDone)
现在我看到
QObject(0x2647bb040f0)
通过
qDebug()删除
\u printThread
不会更改指针地址,即使删除,它仍可能显示
QObject(0x2647bb040f0)
。另外,onPrintDone可以在
deleteLater
机制实际删除
QThread
之前调用。最后,任务管理器向您显示应用程序的内存使用情况,当您删除对象时,内存不一定会减少。您必须使用检漏仪工具。