Где здесь утечка памяти?
QT mainwindow.cpp
#include "mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("Test");
mainWidget = new QWidget(this);
mainLayout = new QVBoxLayout();
question = new QLabel("Hello world", mainWidget);
mainWidget->setLayout(mainLayout);
mainLayout->addWidget(question);
setCentralWidget(mainWidget);
}
MainWindow::~MainWindow()
{
}
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QVBoxLayout>
#include <QLabel>
#include <QWidget>
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
QLabel *question;
QVBoxLayout *mainLayout;
QWidget *mainWidget;
};
#endif // MAINWINDOW_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Самое простое приложение на свете. Вот что говорит Valgrind
Текстовый вывод Valgrind
valgrind --leak-check=full ./untitled
==57961== Memcheck, a memory error detector
==57961== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==57961== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==57961== Command: ./untitled
==57961==
==57961==
==57961== HEAP SUMMARY:
==57961== in use at exit: 340,060 bytes in 7,722 blocks
==57961== total heap usage: 70,991 allocs, 63,269 frees, 82,974,658 bytes allocated
==57961==
==57961== 288 (256 direct, 32 indirect) bytes in 1 blocks are definitely lost in loss record 195 of 322
==57961== at 0x483B7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==57961== by 0x8E872F4: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961== by 0x8E879B8: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961== by 0x8E88FDC: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961== by 0x8E9006C: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961== by 0x94E09D9: ??? (in /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==57961== by 0x94E16AF: ??? (in /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==57961== by 0x94DEB82: ??? (in /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==57961== by 0x94E004D: ??? (in /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==57961== by 0x94E3DBF: XML_ParseBuffer (in /usr/lib/x86_64-linux-gnu/libexpat.so.1.6.11)
==57961== by 0x8E8DF42: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961== by 0x8E8E37B: ??? (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.12.0)
==57961==
==57961== LEAK SUMMARY:
==57961== definitely lost: 256 bytes in 1 blocks
==57961== indirectly lost: 32 bytes in 1 blocks
==57961== possibly lost: 0 bytes in 0 blocks
==57961== still reachable: 339,772 bytes in 7,720 blocks
==57961== suppressed: 0 bytes in 0 blocks
==57961== Reachable blocks (those to which a pointer was found) are not shown.
==57961== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==57961==
==57961== For lists of detected and suppressed errors, rerun with: -s
==57961== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
Ответы (2 шт):
Я могу и ошибаться, так как в QT не работал, и знаю его очень поверхностно. Но, по мне, очевидно:
- MainWindow _ родитель QMainWindow, а он в свою очередь является QWidget _ ом.
- MainWindow имеет указатель
mainWidgetна свою копию (другой QWidget) и имеет еще один виджет:question = new QLabel("Hello world", mainWidget);, который, по всей видимости,размещается в mainWidget.
Так вот: когда удаляется MainWindow w, его родитель не может удалять этот самый question, так как он размещен в другом виджете.
Как исправить:
Если классу нужен указатель на другой виджет(свою копию), то в деструкторе явно удалить эту копию
delete mainWidgetИли просто(не понимаю зачем классу его копия и еще другой, не принадлежащий ему, а этой копии) убрать этот самый указатель
QWidget *mainWidgetи исправить:question = new QLabel("Hello world");
Если гуру меня подправят, буду благодарен. P.S. текстовый вывод Valgrind тут не нужен оказался....
QMainWidget имеет virtual деструктор. Так как он у Вас объявлен явно, то Вам следует сделать его тоже virtual. Возможно дело в этом.
