内存泄露问题
大家好,最近用QT开发UI,需要创建独立的窗口,但是发现关闭新创建的窗口时存在内存泄露问题,网上找了各种方法都不好使(包括设置WA_DeleteOnClose标志,重载closeEvent并调用delete this)。例子很简单,点击主窗口按钮出现一个新的Widget,新Widget上点击上面的close关闭。但是通过Windows内存管理器发现点击打开按钮进程内存增加,点击关闭按钮内存减少,但是增加和减少的量不一致,总是有几时KB的内存泄露问题。整个过程并没有为新的Widget设置parent,请教大家这是什么原因?(移植到ARM上也是一样的情况)
贴点儿代码好说明问题:
主窗口点击按钮通过new创建新的Widget:
void MainWindow::on_pushButton_clicked()
{
TestWidget *test = new TestWidget();
test->show();
}
新Widget的头文件:
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
class TestWidget : public QWidget
{
Q_OBJECT
public:
TestWidget();
~TestWidget();
protected slots:
void onReturnButtonClicked();
void closeEvent(QCloseEvent *event);
private:
QPushButton *btn_close;
QPushButton *btn_tmp;
QVBoxLayout *layout;
};
新Widget的CPP文件:
#include "testwidget.h"
TestWidget::TestWidget()
{
this->setFixedSize(480, 272);
this->setAttribute(Qt::WA_DeleteOnClose, true);
this->setParent(NULL);
btn_close = new QPushButton("close");
btn_tmp = new QPushButton("tmp");
connect(btn_close, SIGNAL(clicked()), this, SLOT(onReturnButtonClicked()));
layout = new QVBoxLayout();
layout->addWidget(btn_close);
layout->addWidget(btn_tmp);
this->setLayout(layout);
}
void TestWidget::closeEvent(QCloseEvent *event)
{
delete this;
}
TestWidget::~TestWidget()
{
delete(layout);
delete(btn_close);
delete(btn_tmp);
}
void TestWidget::onReturnButtonClicked()
{
this->close();
}
各位对不住,第一次来,没分,先给100分吧。 内存泄露 --------------------编程问答-------------------- 1.
TestWidget(QWidget *parent) : QWidget(parent)
{
btn_close = new QPushButton("close", this);
btn_tmp = new QPushButton("tmp", this);
}
2.去掉this->setParent(NULL);
3.去掉
delete this;
delete(layout);
delete(btn_close);
delete(btn_tmp);
不需要你做无用功,Qt垃圾回收机制帮你做了,只要你的widget的父类是QObject或间接QObject
4.TestWidget *test = new TestWidget(this);
就不会有内存泄露了 --------------------编程问答-------------------- 可以保存该Widget的指针为成员变量,首次显示时创建即可。
需要弹出效果也可改用QDialog。 --------------------编程问答--------------------
非常感谢您的谢谢,我有几个疑问,希望和您一起探讨:
1. 按照您说的QT自动回收,前提是设置了WA_DeleteOnClose吧,也就是说下面行代码是不可少的是吗?
this->setAttribute(Qt::WA_DeleteOnClose, true);
2. 主窗口中我通过点击按钮创建新的Widget:
TestWidget *test = new TestWidget();
但是我没有办法调用delete test,一旦调用,新的Widget就消失了,那么这个new出来的TestWidget就是内存泄露了吗?还是说WA_DeleteOnClose方式会自动释放自身?
3. 从任务管理器确实看到点击打开和关闭按钮前后,进程占用的内存变少了,您知道是什么原因吗? --------------------编程问答-------------------- @LazyDreamHunter
忘记补充一点,需求中,我的主窗体MainWindow永远不会close,根据QT子窗体释放机制,那么即使为TestWidget指定了parent为MainWindow,MainWindow不关闭,TestWidget也不会释放,我的理解正确吗?
TestWidget *test = new TestWidget(this);
--------------------编程问答-------------------- 嗯,是这样子的 --------------------编程问答-------------------- 如果是这样的,
你只需要
if (pTest != NULL)
delete pTest;
pTest = new TestWidget();
pTest是mainwidget的成员变量,或者,函数clicked的静态变量,初始赋值= null --------------------编程问答-------------------- 其他的该指向父类的就指向父类, --------------------编程问答--------------------
您的意思是TestWidget不设置parent,但是只创建一次。
而TestWidget中new出来的close和tmp按钮要把parent设置成TestWidget:
btn_close = new QPushButton("close", this);
btn_tmp = new QPushButton("tmp", this);
这样在TestWidget调用close的时候,这两个按钮就自动释放了是吗?
--------------------编程问答-------------------- 基本可以这木理解,
if (pTest != NULL)
delete pTest;
pTest = new TestWidget();
我的意思是,你如果要重复new TestWidget(),如果pTest不空的话,先删除,再new,这要就不会有必须要mainwidget退出才回收new出来的内存了。
但我觉得这样做没有必要,有1分TestWidget就行了,如果你真的要重头再来的话,只需在TestWidget,提供一个init接口,这样就不需要每次单击时,都要new了,看你怎么做了 --------------------编程问答--------------------
一直很迷惑这行代码:
this->setAttribute(Qt::WA_DeleteOnClose, true);
这个需要吗?只能通过它去释放TestWidget的children比如btn_close和btn_tmp,而不能主动释放test自身这个指针? --------------------编程问答-------------------- 这个可以不要 --------------------编程问答-------------------- 只要你的testWidget的孩子,父指针都指向testWidget,这个在delete testWidget的时候,testWidget会删除掉她的所有的孩子
补充:移动开发 , Qt