Невозможно определить причину утечки памяти в QDialog

Я делаю проект, использующий Qt с некоторыми настроенными QDialogs для пользовательского ввода. Из-за аппаратных ограничений моего блока разработки я хочу отслеживать использование памяти моим приложением. Как я исполняю диалог.

1 void MainWindow::callDialog() {
2     DlgPopConfig dialog(&theApp->cfgPop, m_fnPopCfg, this);
3     dialog.exec();
4     m_fnPopCfg = dialog.fileName();
5     lbl_fnPopCfg->setText(m_fnPopCfg);
6 }

Поскольку диалог является локальной переменной, я ожидаю, что он будет создан в стеке и уничтожен сразу же после завершения функции (после строки 5). Когда приложение многократно открывает и закрывает диалоговое окно, его использование памяти увеличивается, и оно никогда не возвращается к начальным значениям ['Memory (Working Set)' and 'Memory (Private Working Set)' столбцы диспетчера задач. Я использовал Application Verifier, включающий все основные тесты, и он не показывает ошибок ". Образец памяти выглядит следующим образом (числовые значения составлены только для иллюстрации):

  • Запуск приложения (рабочий набор = 12000K, закрытый набор = 6000K)
  • Открытый Диалог-1 (рабочий набор = 14000К, закрытый набор = 7000К)
  • Диалог закрытия (рабочий набор = 12010K, закрытый набор = 6005K)
  • Открытый Диалог-2 (рабочий набор = 14020К, закрытый набор = 7000К)
  • Диалог закрытия (рабочий набор = 12010K, закрытый набор = 6008K)
  • Открытый Диалог-3 (рабочий набор = 14080К, закрытый набор = 7010К)
  • Диалог закрытия (рабочий набор = 12040K, закрытый набор = 6008K)
  • ...

Итак, есть идея отследить причину проблемы? (На самом деле, я также сталкиваюсь с подобной проблемой при использовании статических методов QFileDialog getOpenFileName, getSaveFileNameи нашел здесь некоторое обсуждение, но, похоже, не решенное)

Изменить Я использую QFormLayout в своих диалогах, и я добавляю виджеты layout->addRow("label text", mywidget);Я сомневаюсь, что уничтожение объекта не удаляет метки чисто.

Редактировать Я создал тестовую программу с QDialog, имеющей десять QLineEdits, используя одну и ту же стратегию добавления виджетов. Проблема все еще существует. (Проблема возникнет в этой тестовой программе, если я часто создаю и закрываю диалог, говорит 10 раз в секунду)

mainwindow.h

#include <QMainWindow>
#include <QPushButton>
#include <QDialog>
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
private:
    QPushButton * button;
private slots:
    void button_click();
};
class Dialog : public QDialog
{
    Q_OBJECT
public:
    explicit Dialog(QWidget *parent = 0);
};

mainwindow.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>

MainWindow::MainWindow(QWidget *parent):QMainWindow(parent)
{
    button=new QPushButton(this);setCentralWidget(button);
    connect(button,SIGNAL(clicked()),SLOT(button_click()));
}
void MainWindow::button_click()
{
    Dialog d(this);
    d.exec();
}
Dialog::Dialog(QWidget *parent):QDialog(parent)
{
   QFormLayout*layout=new QFormLayout(this);
   setLayout(layout);
   for (int i = 0; i < 10; i++)
   {
       layout->addRow(QString("%1").arg(i+1), new QLineEdit(this));
   }
}
int main(int c,char *argv[])
{
    QApplication a(c,argv);
    MainWindow w;
    w.show();
    return a.exec();
}

Платформа

  • Win 7 x64, MinGW 4.7.2 x64 (rubenvb-build), 4 ГБ оперативной памяти
  • Qt 4.8.5 (изначально собран с использованием вышеуказанной цепочки инструментов)
  • Qt-Creator 2.6.1 (встроенный с использованием вышеуказанной цепочки инструментов)

1 ответ

Опоздание на несколько месяцев, но это может помочь следующему человеку, который столкнется с этой проблемой. Я использую PySide, но была та же утечка памяти. Оказалось, что есть два варианта, в зависимости от того, какую информацию вам нужно вернуть из диалогового окна:

1) Запланируйте диалог для удаления, когда вы закончите с ним.

В Python это выглядит так:

dialog = MyDialog(self)
dialog.exec_()
# Do other things with dialog
dialog.deleteLater()

И это должно выглядеть аналогично в вашем коде C++:

void MainWindow::button_click()
{
    Dialog d(this);
    d.exec();
    // Do other things with d
    d.deleteLater()
}

2) Установите атрибут WA_DeleteOnClose.

В итоге я включил это в конструктор пользовательского диалога:

    self.setAttribute(PySide.QtCore.Qt.WA_DeleteOnClose)

Который должен выглядеть примерно так в вашем C++ коде:

Dialog::Dialog(QWidget *parent):QDialog(parent)
{
   QFormLayout*layout=new QFormLayout(this);
   setLayout(layout);
   setAttribute(Qt::WA_DeleteOnClose);
   for (int i = 0; i < 10; i++)
   {
       layout->addRow(QString("%1").arg(i+1), new QLineEdit(this));
   }
}

Оба из них исправили утечку памяти для меня, за исключением того, что она иногда будет пропускать 4 КБ, если я буду открывать / закрывать диалог очень быстро несколько раз подряд. Извините за Python-ориентированный ответ - надеюсь, это указывает людям верное направление.

Другие вопросы по тегам