QT程序占用内存过高



1.问题:

   最近正在测试写的QT应用程序,QT程序运行在S3C2440板子上的linux系统中,测试的过程中发现一个奇怪的问题,QT程序占用内存一次比一次大。比如第一次开机QT应用程序运行内存为30M,在运行一段时间后增加到33M,此时我将板子断电。第二次上电重启,怪事发生了,此时运行内存达到了34M,运行一段时间后达到37M。依次类推,最后QT程序因为占用内存过大被linux系统直接杀掉了,后面直接就起不来了。这个问题我百思不得其解,按理即使有内存泄露,断电重启它应该也会复原啊,为何内存却一次比一次大呢?

2.原因:

   经过多天的查找终于找到了故障点,原来是因为我程序中使用了SQLite数据库导致的。具体的原因是,我在QT程序中使用SQLite数据库存取历史数据,存取的历史数据是由下位机传上来的,每5秒存一次,这样每天存取的数据量达到17280条,量比较大。而导致内存一次比一次大的根本原因就在于我获取数据库最后一条记录的操作方式,由于我使用文件号的形式存取数据,所以每次仪器开机时都要去查看数据库中最后一条历史记录的文件号,然后以此文件号为基础向数据库中添加历史记录(文件号唯一代表每条历史记录,不能重复)。下面是我获取文件号的代码:

QSqlQuery history_query;

    history_query.exec("SELECT * FROM history");

    if(!history_query.next())

    {

        g_iFileNum = 0;

    }

    else

    {

        history_query.last();

        g_iFileNum = history_query.record().value("FileNumber").toInt() + 1;

    }

错误点就在于last()函数的使用,last()函数会将数据库中所有的记录都放到了history_query的缓冲区中,如果数据库中history表数据量庞大的话就会造成内存急剧攀升,此段代码在主界面的构造函数之中,以后随着历史记录的增多,开机内存会越来越大,以致出现上述故障。

注意:下面这种获取最后一条历史记录的方式同样会造成上述故障。

QSqlTableModel *model;  //用于显示历史记录

    model = new QSqlTableModel(this);

model->setTable("history");

model->setEditStrategy(QSqlTableModel::OnFieldChange);

    model->select();

    while (model->canFetchMore())

    {

//        model->clear(); //使用clear不能达到预期效果,即无效

          model->fetchMore();

    }

    int row_num = model->rowCount();

    g_iFileNum = model->record(row_num - 1).value("FileNumber").toInt() + 1;

 

3.解决方案:

    我的解决方案就是使用排序来获取最后一条历史数据,实验表明此种方式将避免上述出现的问题,效果良好,代码如下:

    //

    // 历史记录部分的处理

//

QSqlTableModel *model;  //用于显示历史记录

    model = new QSqlTableModel(this);

    model->setTable("history");

    model->setEditStrategy(QSqlTableModel::OnFieldChange);

 

    /* 获取文件号(取文件号最好不要用last函数或者fetchMore函数,数据库大时会造成系统崩溃) */

    model->setSort(0,Qt::DescendingOrder);  //降序排列

    model->select();

 

    model->query().first(); //必须使用,因为排序后当前行不是第一行,而是第255行

    g_iFileNum = model->query().record().value("FileNumber").toInt() + 1;

 

    /* 获取文件号后将数据库恢复为升序排列 */

    model->setSort(0,Qt::AscendingOrder);  //升序排列

    model->select();

### QT 多线程 CPU 占用解决方案 #### UI 控件频繁刷新的影响 当应用程序中的UI控件更新过于频繁时,会显著增加CPU负载。为了减少这种影响,可以采取措施降低UI刷新频率或优化刷新逻辑[^1]。 #### 使用 `QCoreApplication::processEvents` 的局限性 尝试通过循环调用 `QCoreApplication::processEvents()` 来保持界面响应性的方法可能并不总是有效。这种方法可能会导致不必要的事件处理,反而增加了系统的负担[^2]。 ```cpp // 避免这种方式来防止主界面卡顿 QElapsedTimer et; et.start(); while (et.elapsed() < 100) QCoreApplication::processEvents(); // 可能造成额外开销 ``` #### 合理设置线程优先级 对于多线程应用来说,合理配置各工作线程的优先级非常重要。需要注意的是,只有在线程处于等待状态并已加入调度器队列的情况下,调整其优先级才有意义;如果线程池为空,则新创建的线程将按照它们被添加到池中的顺序依次运行[^3]。 ```cpp // 设置线程优先级示例 QThread* thread = new QThread(this); worker->moveToThread(thread); thread->start(QThread::HighPriority); // 提该线程的相对重要程度 ``` #### 推荐的最佳实践 - **异步操作**:尽可能利用Qt内置的支持非阻塞I/O的功能,比如网络请求、文件读等都应采用异步方式完成。 - **任务分解**:将耗时较长的任务拆分为多个子任务,在不同时间点逐步执行,从而减轻单次计算的压力。 - **资源管理**:确保及时释放不再使用的内存和其他系统资源,避免因泄漏造成的性能下降。 - **监控工具**:借助专业的分析软件如Valgrind、Perf等定位具体消耗大量CPU周期的地方,并针对性改进代码效率。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值