malloc/calloc/realloc 必须找到对应的 free,且覆盖所有代码路径(提前 return 也算);指针被覆盖前先 free 原来的一句话:"配对不齐是泄漏,洞不齐是碎片;泄漏少总量,碎片乱布局。"
内存泄漏 = 申请了不释放(该还没还,总量变少);内存碎片 = 释放了但空间不连续(还了但乱,总量够却申请不到大块)。泄漏是"忘还",碎片是"还了但乱"。
void f(){ int *p = malloc(100); /* 忘 free */ } → 每次调用泄漏 100 字节。查法 = malloc/free 一一配对int *p = malloc(100); p = malloc(200); → 第一个 100 字节地址被覆盖丢了,没法 free → 泄漏。指针被重新赋值前必须先 freeint *p = malloc(100); if (flag) return; free(p); → 提前 return 漏了 free,也是泄漏(配对要覆盖所有路径)| 内存泄漏 | 内存碎片 | |
|---|---|---|
| 本质 | 该还没还(总量变少) | 还了但乱(总量够、不连续) |
| 现象 | 可用内存持续减少 | 大块分配失败 |
| 原因 | malloc 不配对 free | 随机分配/释放不同大小 |
| 查法 | malloc/free 配对检查 | 看分配失败时空闲块分布 |
| 治理 | 配对、RAII、内存池归还 | 合并算法、固定大小块、内存池 |
int *p = malloc(100); p = malloc(200); → 泄漏(第一个 100 字节地址被覆盖丢失,没法 free)xPortGetFreeHeapSize() 看剩余堆反复减少 = 泄漏 ② 包装记账(my_malloc/my_free 计数器,申请数−释放数 ≠ 0 即泄漏)③ 记录调用点(带 __FILE__/__LINE__ 打印谁申请的)④ PC 开发期 valgrind / AddressSanitizer 预检| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| 堆 vs 栈 | 泄漏/碎片全发生在堆——栈天然没有这两个问题 | 以为栈也有泄漏 |
| 内存池 | 治理碎片的第一手段:固定大小块 + 归还配对 | 以为池子能顺带治好泄漏 |
| 野指针 | 悬垂(用了已释放)vs 泄漏(该还没还)——一对反向错误 | 把悬垂和泄漏混为一谈 |
| FreeRTOS 堆管理 | heap_1~heap_5:不同策略对应不同碎片/泄漏特性 | 以为 FreeRTOS 内存和裸机 malloc 一样 |
2026-08-03
每主题一页,复习时只翻本目录。