1、内存泄漏基础:什么是内存泄漏、内存泄漏的危害、常见的内存泄漏类型

1.1 什么是内存泄漏?

内存泄漏,说白了就是「借了不还」。

你向操作系统申请了一块内存,用完之后忘了释放。这块内存就永远「失踪」了——别人用不了,系统也收不回来。

我刚开始做C++开发时,觉得这玩意儿离自己很远。直到有一次,我写了一个图像处理模块,跑了一整天,内存从200MB涨到了2GB。嗯,那时候我才真正意识到:内存泄漏不是小问题。

用代码说话:

// 典型的内存泄漏
void leakExample() {
    int* p = new int(42);   // 申请内存
    // 忘记 delete p;
    // p 指向的内存再也无法释放
}

你想想看,每次调用这个函数,就丢失4个字节。如果被循环调用一万次呢?十万次呢?

核心定义:内存泄漏是指程序在运行过程中,动态分配的内存没有被正确释放,导致这部分内存无法被再次使用,直到程序结束。

1.2 内存泄漏的危害

很多人觉得:「程序退出时系统会回收所有内存,怕什么?」

这话没错,但问题在于——你的程序可能根本不会正常退出。

我遇到过最惨的一次:一个Qt桌面应用,用户连续操作8小时后,界面卡死,鼠标都动不了。最后发现是某个定时器回调里,每次new一个QWidget,却从不delete。

内存泄漏的危害,我总结为四点:

危害 表现 后果
性能下降 程序越来越慢 用户抱怨,体验极差
内存耗尽 OOM(Out of Memory) 程序崩溃,数据丢失
系统不稳定 拖慢整个系统 其他进程也被影响
难以排查 问题复现困难 开发成本飙升

警告:在嵌入式设备或服务器端,内存泄漏是致命的。我曾经见过一个后台服务,运行两周后内存占用达到90%,最终被系统kill掉。那是一个线上事故,凌晨3点被电话叫醒的感觉……你懂的。

1.3 常见的内存泄漏类型

搞清楚了危害,咱们来看看实际开发中,内存泄漏到底长什么样。我把它分成三类:

类型一:堆内存泄漏

这是最常见的。new了没delete,malloc了没free。

// 堆内存泄漏示例
void processData() {
    char* buffer = new char[1024];
    // 处理数据...
    // 忘记 delete[] buffer;
}

我个人习惯:能用智能指针就用智能指针。std::unique_ptr、std::shared_ptr,它们能帮你自动管理生命周期。

类型二:资源泄漏

不仅仅是内存。文件句柄、数据库连接、GDI对象、Qt的QPixmap……这些都属于系统资源。

// 资源泄漏示例(Qt中常见)
void loadImages() {
    QPixmap* pix = new QPixmap("big_image.png");
    // 用完后忘记 delete pix;
    // 每次调用都泄漏一个QPixmap对象
}

我曾经在项目中排查过一个诡异问题:程序运行一段时间后,所有图片都显示不出来。最后发现是QPixmap对象泄漏,导致GDI句柄耗尽。Windows下每个进程的GDI句柄上限是10000个,超过了就罢工。

类型三:逻辑泄漏

这种最隐蔽。内存释放了,但释放的时机不对,或者释放的方式不对。

// 逻辑泄漏示例
class MyWidget : public QWidget {
    QTimer* m_timer;
public:
    MyWidget() {
        m_timer = new QTimer(this);  // 父对象管理
        // 看起来没问题,但...
    }
};

// 如果手动 delete MyWidget 对象,但忘记 stop 定时器
// 定时器回调中可能还在访问已销毁的对象
// 这叫野指针,比内存泄漏更可怕

避坑指南:我曾经在Qt中犯过一个低级错误——在析构函数里没有调用deleteLater(),导致QObject的子对象没有被正确清理。嗯,Qt的父子对象机制虽然方便,但千万别以为它万能。

1.4 知识体系总览

为了让你更直观地理解本章内容,我画了一张图:

内存泄漏基础 什么是内存泄漏 借了不还 动态分配未释放 内存泄漏的危害 性能下降 内存耗尽 系统不稳定 排查困难 常见泄漏类型 堆内存泄漏 资源泄漏 逻辑泄漏 预防 > 排查 > 修复

这张图把本章的核心内容串起来了。从定义到危害,再到三种常见类型,一目了然。

最后说一句:内存泄漏不是洪水猛兽。你只要养成好习惯——用智能指针、注意资源释放、定期做内存分析——它基本不会找上你。

嗯,下一章咱们聊聊怎么用工具定位内存泄漏。不过那是后话了。

本章小结:

  • 内存泄漏 = 申请了内存但没释放
  • 危害包括性能下降、内存耗尽、系统不稳定、排查困难
  • 三种常见类型:堆内存泄漏、资源泄漏、逻辑泄漏
  • 预防比修复更重要

可可精品资料库