1 概述
设备开机使用一段时间后软件UI响应慢,不流畅,有明显的卡顿。
2 分析和验证
2.1 分析过程
通过gdb attach查看设备空闲状态主线程(UI线程)正在执行的操作,发现跟图像和gif动图有关
联想到跟动图提示有关的对话框,查看代码发现跟Qt文档示例用法一致
查看文档发现QLabel::setMovie方法不会在QLabel和QMovie间建立父子关系,QMovie对象构造的时候也没有传入parent,所以也就不会在QLabel析构的时候把QMovie析构。这个QMovie对象就存在内存泄漏问题,且没有stop,所以会一直在UI线程占用资源播放gif动画。这样,每次使用改对话框的功能都会增加QMovie对象导致UI响应越来越慢。
2.2 Demo验证
通过加速的方式验证,每次使用该对话框的功能多加几十个这样的QMovie对象。
系统状态:刚开机空闲状态该软件CPU使用率2%左右,多次测试后UI响应慢,空闲状态CPU使用率25%左右,因为存在内存泄漏,内存一直在增加。
通过gdb attach查看空闲状态主线程(UI线程)正在执行的操作,发现跟之前的设备一致。
3 修改方案
关闭对话框的时候(重写closeEvent)停止QMovie动画并释放资源。附个ChatGPT的截图
2024-05-10补充:
如果频繁新建和关闭gif对话框,该问题又复现了,因为closeEvent没有被正确调用或者调用的时机不合适。
在Qt中,closeEvent是在对话框即将关闭时被调用的。如果对话框被删除而没有显示(例如,通过调用delete而不是close),则closeEvent可能不会被调用。此外,如果对话框是由于窗口管理器或者操作系统级别的关闭事件而关闭的,而不是通过代码显式调用close,那么closeEvent也可能不会被调用。
为了确保QMovie在对话框销毁时总是被正确地停止和删除,应该将清理代码放在析构函数中。析构函数是在对象即将被销毁时自动调用的,这意味着无论对象是如何被销毁的,析构函数都会被执行。
4 思考
参考Qt文档的示例,使用过程中还需要考虑好对象的生命周期,以及详细阅读相关接口的说明。