为啥在 Qt 中继承 QWidget 类时出现内存泄漏

Posted

技术标签:

【中文标题】为啥在 Qt 中继承 QWidget 类时出现内存泄漏【英文标题】:why do i have memory leak while doing inheritance of QWidget class in Qt为什么在 Qt 中继承 QWidget 类时出现内存泄漏 【发布时间】:2018-07-03 11:21:38 【问题描述】:

我是 C++ 新手。我试图通过继承基类QWidget来设计一个类 但是我在通过 new 创建这个类时遇到了内存泄漏。 下面我有我的类和主应用程序的代码 sn-p

#include "QWidget"
#include "QDebug"
#include "ui_myobject.h"

namespace Ui     
    class MyObject;    


class MyObject : public QWidget    
    Q_OBJECT    
public:       
    explicit MyObject();
    ~MyObject();
    Ui::MyObject *ui; 
;

#include "myobject.h"
#include "ui_myobject.h"

MyObject::MyObject() : QWidget(),ui(new Ui::MyObject)    
    ui->setupUi(this);
    qDebug() << "MyObject Initilised";

MyObject::~MyObject()    
    delete ui;
    qDebug() << "MyObject Deinitilised";    


class Application : public QWidget

    Q_OBJECT    
public:
    explicit Application(QWidget *parent = 0);    
    ~Application();     
    MyObject *m_MyObject;       
;  

Application::Application(QWidget *parent) :QWidget(parent),ui(new Ui::Application)    
ui->setupUi(this);    
    

我通过按钮的点击释放槽调用下面的函数

void somefunction()
    
      m_MyObject = new MyObject();
                //mAlarm_main->Alarm();    
                m_MyObject->show();    
                delete m_MyObject;
    


int main(int argc, char *argv[])

#if (QT_VERSION >= QT_VERSION_CHECK(5, 0, 0))
    ; // Qt5 uses different graphical backend
#else
    QApplication::setGraphicsSystem("raster");
#endif

    QApplication a(argc, argv);
    Application w;

    // uncomment this line to remove window frame
    //w.setWindowFlags(Qt::FramelessWindowHint);

    w.setGeometry(0,0,800,480);

    w.show();

    return a.exec();

当我调用某个函数时,我的应用程序中出现内存泄漏,我使用 top 命令查看它的堆栈大小,在 200 timesmy 应用程序崩溃后它不断增加 2 mb。我正在删除我的对象,但仍然发生了一些内存泄漏,是否有任何不同的方法可以删除 QWidget

如果我不调用 m_MyObject->show();功能比内存泄漏不会发生。

【问题讨论】:

如果它是一个 qobject 不要删除它。在构造它时将其传递给父级。 doc.qt.io/qt-5/objecttrees.html 我将 parent 传递给它,但结果是一样的。 你在哪里使用Application对象?为什么你认为问题在于打电话给somefunction() 那是你展示的完整代码吗? 我已经更新了我的主要功能的代码 【参考方案1】:

在下面的代码中,您删除了刚刚显示的小部件(方法 `show' 没有阻塞)。我相信它会导致未定义的行为,并且可能会导致您担心的内存泄漏:

  m_MyObject = new MyObject();
  m_MyObject->show();
  delete m_MyObject;

假设您一次只需要一个MyObject,我建议只创建一次MyObject(不要忘记默认使用nullptr初始化它)

if (!m_MyObject)
    m_MyObject = new MyObject();
m_MyObject->show();

另一种方法(看起来这个小部件应该显示为一个单独的窗口)是设置Qt::WA_DeleteOnClose 属性(有关详细信息,请参阅QWidget::close)。

    m_MyObject = new MyObject();
    m_MyObject->setAttribute(Qt::WA_DeleteOnClose, true);
    m_MyObject->show();

示例:

#include <QApplication>
#include <QPushButton>

int main(int argc, char* argv[])

    QApplication app(argc, argv);

    QWidget* w = nullptr;
    QPushButton b;
    b.setText("Button");
    b.connect(&b, &QPushButton::clicked, [&w]() 
        w = new QWidget();
        w->setAttribute(Qt::WA_DeleteOnClose, true); // ADD THIS LINE
        w->show();
        // delete w; // DON'T DO IT
    );
    b.show();

    return app.exec();

【讨论】:

m_MyObject = new MyObject(); m_MyObject->setAttribute(Qt::WA_DeleteOnClose, true); m_MyObject->显示(); m_MyObject->close();删除 m_MyObject; 我这样做了,但仍然发生内存泄漏。 移除 m_MyObject->close();删除 m_MyObject; 删除了 m_MyObject->close(); ,结果是一样的。 删除 m_MyObject 怎么样; ?

以上是关于为啥在 Qt 中继承 QWidget 类时出现内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

C#中继承类为啥可以通过属性访问基类的私有字段。

为啥我不能访问派生构造函数的成员初始化列表中继承的受保护字段?

C#中继承问题

C#中继承对象的内存分配

从 Qt5Widgets 调用 setFixedSize() 时出现未处理的异常

为啥我在删除 char* 时出现内存异常