Qt中QTreeview,QLIstView,QTableview等表格控件更新数据model时内存泄漏的问题

前言

最近开发redis可视化ui,连到了阿里云上的redis,这个redis的hash动辄好几百条数据,拿到后写到QTableview中。测试良好。
但测试一段时间后,点了几十条hash,拿到了几十条hash数据,QTableview也更新了几十次,在进行其他操作的时候,出现了程序崩溃。
于是就想,是不是发生了内存泄漏。

场景

假设有一个QTableview,名叫table
先看下面的代码,功能是清空TableView

void clearTreeView(){
	ui->view->setModel(nullptr);
}

再看下面的代码,功能是设置数据

void setTableData(){
	QStandardItemModel* model = new QStandardItemModel();
	ui->view->setModel(model);
}

可以看到,设置数据时,QStandardItemModel为指针,new了一个对象,但当我们清空时候,原来的model会不会被delete呢?
我们来验证一下。

验证

新建一个项目,界面是这样的
在这里插入图片描述

为了验证是否释放内存,我们新建一个QObject类,名叫QModel,继承QStandardItemModel,重写析构函数。
头文件qmodel.hpp:

#ifndef QMODEL_HPP
#define QMODEL_HPP

#include <QObject>
#include <QStandardItemModel>
class QModel : public QStandardItemModel
{
    Q_OBJECT
public:
    explicit QModel(QObject *parent = nullptr);
    ~QModel();
signals:

};

#endif // QMODEL_HPP

头文件实现文件qmodel.cpp

#include "qmodel.hpp"
#include <QDebug>
QModel::QModel(QObject *parent) : QStandardItemModel(parent)
{

}

QModel::~QModel()
{
	// 析构函数
    qDebug() << "model delete";
}

ui窗口连接好信号槽,分为加载数据和清空数据
这里每按一次加入数据按钮,就添加1-10000数字。
table view控件名叫tableView

#include "mainwindow.hpp"
#include "ui_mainwindow.h"

#include <qmodel.hpp>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    // 添加数据信号槽,lambda函数写法
    connect(ui->pushButton, &QPushButton::clicked, this, [=](){
    	// 继承QStandardItemModel的那个类
        QModel* model = new QModel();
        for(int i = 0; i < 10000; i++){
            model->appendRow(new QStandardItem(QString::number(i)));
        }
        ui->tableView->setModel(model);
    });
    connect(ui->pushButton_2, &QPushButton::clicked, this, [=](){
        ui->tableView->setModel(nullptr);
    });
}

MainWindow::~MainWindow()
{
    delete ui;
}

打开任务管理器。
运行程序。
可以看到,程序最开始所占内存大小
在这里插入图片描述
9396K。
后面就不放图了,这里只说数据。
我们来加入数据
在这里插入图片描述
此时内存占用变为12724K,显著提高。
我们来清空数据。
此时内存占用12932K,不减反增。
析构函数按理会打印model delete字样,但是qtcreator控制台什么也没发生,很显然,数据清空后,资源没有释放,发生了内存泄漏。
再点击加入数据。
内存占用15100K,变得更多了。
清空。
内存15228K。

结论

在通过setModel(nullptr)方式清空表格数据时,原来表格内的数据model并不会主动释放,会仍存在于内存中,造成了内存泄漏,如果我们长时间运行软件,频繁更新数据模型,最终会导致程序崩溃。
想想,一个小破软件,占用内存好几个G。感人。

解决

我们在重新setModel时,需要手动delete原来的数据模型。
通过model方法可以拿到model

void setData(){
	delete ui->tableView->model();
	ui->tableView->setModel(nullptr);	// 或新model
}

此时在运行。
加入数据,12756K。
清空,11132K。
加入数据:13184K。
清空:11720K。
反复横跳。
另外,在QStandardItemModel被析构时,其内部存储的QStandardItem是否会释放,官方文档对QStandardItemModel有下列描述:

[virtual] QStandardItemModel::~QStandardItemModel()
Destructs the model. The model destroys all its items.
销毁模型,模型会销毁所有的项目。

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值