Qt UI 应用中图片未释放导致内存泄露:从一行 QPixmap 分析到全链路解决


支持作者,点击京东购买《Yocto项目实战教程》



一、问题背景:浏览图片时 UI 卡顿,内存逐渐增加

在对一款基于 Qt 的文件阅读 UI 应用进行调试时,发现:

  • 每次点击切换页面,有图片重新加载操作,UI 系统开始卡顿
  • 使用 top 查看,RES 内存持续上涨,即使 CPU 使用率不高
  • 应用运行 1-2 分钟后,系统突然卡死或者被 OOM 杀掉

类似问题应用很普遍。本文将分析一个简单示例,说明这类问题如何发生,如何确诊与优化。


二、原始代码:QPixmap 未 delete 导致泄露

// 错误用法:每次加载都新建一个 QPixmap
QPixmap *pix = new QPixmap("/tmp/img1.png");
label->setPixmap(*pix);  // 未 delete pix

视觉上看不出问题,但实际上每次操作后旧的 QPixmap 已经无法释放,最终导致 heap 内存爆表。


三、完整示例:Qt5/Qt6 UI 应用演示

文件名:leaky_pixmap_demo.cpp
#include <QApplication>
#include <QLabel>
#include <QPushButton>
#include <QVBoxLayout>
#include <QPixmap>
#include <QWidget>

class LeakyWindow : public QWidget {
    Q_OBJECT
public:
    LeakyWindow(QWidget *parent = nullptr) : QWidget(parent) {
        QVBoxLayout *layout = new QVBoxLayout(this);

        label = new QLabel("\u70b9\u51fb\u6309\u94ae\u52a0\u8f7d\u56fe\u7247", this);
        layout->addWidget(label);

        QPushButton *btn = new QPushButton("\u52a0\u8f7d\u56fe\u7247", this);
        layout->addWidget(btn);

        connect(btn, &QPushButton::clicked, this, &LeakyWindow::loadImage);
    }

private slots:
    void loadImage() {
        QPixmap *pix = new QPixmap("/tmp/img1.png");  // 未 delete
        label->setPixmap(*pix);  // 每次切换都有泄露
    }

private:
    QLabel *label;
};

#include "leaky_pixmap_demo.moc"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    LeakyWindow win;
    win.setWindowTitle("QPixmap Leak Demo");
    win.show();
    return app.exec();
}
编译命令
g++ leaky_pixmap_demo.cpp -o leaky_pixmap_demo $(pkg-config --cflags --libs Qt5Widgets)

四、验证泄露效果:切换图片内存持续上涨

运行后,多次点击 “加载图片” 按钮:

top -p $(pidof leaky_pixmap_demo)

观察 RES 内存不断上涨,最终系统卡顿/崩溃

在这里插入图片描述


五、正确使用方法

方案 1:使用栈上对象
QPixmap pix("/tmp/img1.png");
label->setPixmap(pix);  // 自动释放
方案 2:维护成员变量,手动 delete
if (last_pix) delete last_pix;
last_pix = new QPixmap("/tmp/img1.png");
label->setPixmap(*last_pix);

六、问题解析思路:如果面试被问到,如何分析和回答?

接口例:

“UI 卡顿最可能的原因是什么?如果是内存问题,你怎么查看?”

回答结构:
  1. 先看硬挂、CPU 、IO (top/查指标),确诊为内存问题

  2. 解析确诊路径:

    • 应用应用 malloc/new 运行时持续增长
    • 别忘了基于 Qt 系统自带的 QPixmap / QImage / QStringList 等需要手动释放
  3. 用 top + pmap + valgrind 确定泄露点

  4. 解决方案:

    • 转换为栈上对象,或维护类成员变量,精确控制生命周期

结论:UI 系统应用中内存泄露是需要特别讲解和调试的核心区域

  • 一行 new 就可能导致系统纯电路卡死;
  • 内核的 slab/cache 和用户的 heap 有相关联,需要全链路解析
  • 查 /proc/meminfo + 监控 top 折展重要基本技巧


支持作者,点击京东购买《Yocto项目实战教程》



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值