Где здесь утечка памяти?

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

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 шт):

Автор решения: AR Hovsepyan

Я могу и ошибаться, так как в QT не работал, и знаю его очень поверхностно. Но, по мне, очевидно:

  1. MainWindow _ родитель QMainWindow, а он в свою очередь является QWidget _ ом.
  2. 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 тут не нужен оказался....

→ Ссылка
Автор решения: Inquisitions

QMainWidget имеет virtual деструктор. Так как он у Вас объявлен явно, то Вам следует сделать его тоже virtual. Возможно дело в этом.

→ Ссылка