qt - 无法检测 QDialog 内存泄漏的原因

标签 qt memory-leaks qdialog application-verifier

我正在做一个项目,使用 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 行之后)。当应用反复打开和关闭对话框时,它的 mem 使用率上升,并且永远不会返回到初始值 ['Memory (Working Set)' and 'Memory (Private Working Set)' columns of Task经理]。我使用了 Application Verifier,启用了所有基本测试,并且没有显示任何错误。内存模式如下所示(数值仅由插图组成):

  • 应用程序启动(工作集 = 12000K,私有(private)集 = 6000K)
  • 打开 Dialog-1(工作集 = 14000K,私有(private)集 = 7000K)
  • 关闭对话框(工作集 = 12010K,私有(private)集 = 6005K)
  • 打开 Dialog-2(工作集 = 14020K,私有(private)集 = 7000K)
  • 关闭对话框(工作集 = 12010K,私有(private)集 = 6008K)
  • 打开 Dialog-3(工作集 = 14080K,私有(private)集 = 7010K)
  • 关闭对话框(工作集 = 12040K,私有(private)集 = 6008K)
  • ...

那么,有什么想法可以追踪问题的根本原因吗? (其实我在使用静态方法QFileDialog getOpenFileName, getSaveFileName的时候也遇到了类似的问题,找了一些讨论here,不过好像没解决)

编辑 我在对话框中使用 QFormLayout,并通过 layout->addRow("label text", mywidget); 添加小部件,我怀疑对象是否被破坏未能干净地去除标签。

编辑 我用 QDialog 创建了一个测试程序,有十个 QLineEdits,使用相同的添加小部件策略。问题仍然存在。 (如果我频繁地创建和关闭对话框,这个测试程序就会出现这个问题,比如每秒 10 次)

主窗口.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);
};

主窗口.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)、4GB 内存
  • Qt 4.8.5(使用上述工具链本地构建)
  • Qt-Creator 2.6.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));
   }
}

这两个都为我修复了内存泄漏,除了如果我连续多次快速打开/关闭对话框偶尔会泄漏 4kb。很抱歉以 Python 为中心的答案——希望这能为人们指明正确的方向。

关于qt - 无法检测 QDialog 内存泄漏的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15674422/

相关文章:

c++ - QDataStream QIODevice 内存分配

java - 如何在没有源代码的情况下查找 J2EE 应用程序中的内存泄漏

c++ - 在循环中执行移位操作时 C++ 中的内存泄漏

javascript - Jquery/Javascript 内存泄漏

qt - 如何以编程方式关闭 QMenu

c++ - 图像选择区域拉伸(stretch)为矩形

c++ - Qt WindowMaximize 不改变几何(C++)

c++ - 如何在 QT 中将 QDialog 居中?

c++ - 如何从 C++ 扩展的 QQuickItem 创建 QQuickWindow 作为 child ?

c++ - 自定义 QDialog 在 exec() 时导致段错误