Невозможно определить причину утечки памяти в 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-ориентированный ответ - надеюсь, это указывает людям верное направление.