|
|
@@ -26,18 +26,20 @@ created: 2026-07-12
|
|
|
|
|
|
## 五种 heap 算法对比
|
|
|
|
|
|
-| 算法 | 合并空闲块 | 允许释放 | 适用场景 | 推荐? |
|
|
|
-|------|-----------|---------|---------|:----:|
|
|
|
-| heap_1 | 不适用 | ❌ 不能释放 | 只创建不删除的项目 | |
|
|
|
-| heap_2 | ❌ | ✅ | 任务栈大小固定 | ❌ 已过时 |
|
|
|
-| heap_3 | 由C库决定 | ✅ | 标准库可用时 | |
|
|
|
-| **heap_4** | ✅ | ✅ | **通用场景** | **⭐ 推荐** |
|
|
|
-| heap_5 | ✅(跨区域) | ✅ | 内存地址不连续 | |
|
|
|
+| 算法 | 策略 | 合并空闲块 | 允许释放 | 适用场景 | 推荐? |
|
|
|
+|------|------|-----------|---------|---------|:----:|
|
|
|
+| heap_1 | 简单数组分配 | 不适用 | ❌ 不能释放 | 只创建不删除的项目 | |
|
|
|
+| heap_2 | 最佳适应(Best-fit) | ❌ | ✅ | 任务栈大小固定 | ❌ 已过时 |
|
|
|
+| heap_3 | C 库 malloc/free | 由 C 库决定 | ✅ | 标准库可用时 | |
|
|
|
+| **heap_4** | **首次适应(First-fit)** | **✅** | ✅ | **通用场景** | **⭐ 推荐** |
|
|
|
+| heap_5 | 跨区域 First-fit | ✅(跨区域) | ✅ | 内存地址不连续 | |
|
|
|
|
|
|

|
|
|
|
|
|
### heap_1:最简单(不能释放)
|
|
|
|
|
|
+> **"蹲坑不冲水"**:只申请不释放,就像上厕所不冲水——简单粗暴,但只适用于项目启动时一次性创建所有对象的场景。
|
|
|
+
|
|
|
```
|
|
|
初始化: [ 整个堆空间 ]
|
|
|
分配后: [ Task1 ][ Task2 ][ Task3 ][ 剩余 ]
|
|
|
@@ -49,6 +51,8 @@ created: 2026-07-12
|
|
|
|
|
|
### heap_2:最佳适应(过时)
|
|
|
|
|
|
+> **"伤过的心已经变成玻璃碎片"**:最佳适应算法(Best-fit)从满足要求的块中选择最接近请求大小的。问题是不合并相邻空闲块——时间长满是小碎片,大块分配失败。
|
|
|
+
|
|
|
```
|
|
|
释放后: [ Task1 ][ 空闲 ][ Task3 ][ 空闲 ]
|
|
|
↑不合并 ↑不合并
|
|
|
@@ -59,8 +63,14 @@ created: 2026-07-12
|
|
|
|
|
|

|
|
|
|
|
|
+### heap_3:C 库包装
|
|
|
+
|
|
|
+> 标准 C 库 `malloc()`/`free()` 的简单线程安全包装。如果开发环境自带 C 库就可以用,但和裸机 malloc 一样有非确定性问题。
|
|
|
+
|
|
|
### heap_4:第一适应 + 合并(推荐)
|
|
|
|
|
|
+> **首次适应算法**(First-fit):按地址顺序找到第一个足够大的块就用,不追求最优匹配(更快)。**自动合并相邻空闲块**——有人走了,把旁边空位合并成大空间。
|
|
|
+
|
|
|
```
|
|
|
释放后: [ Task1 ][ 空闲 ][ Task3 ][ 空闲 ]
|
|
|
↓自动合并相邻空闲块
|
|
|
@@ -72,6 +82,8 @@ created: 2026-07-12
|
|
|
|
|
|
### heap_5:跨区域 heap_4
|
|
|
|
|
|
+> **"杀鸡焉用牛刀"**:能合并不连续的内存区域,但开销大。除非你的内存物理上就不连续(比如外扩 SARM 和片内 SRAM 要统一管理),否则用 heap_4 就够了。
|
|
|
+
|
|
|
```
|
|
|
内存布局: [ 区域A 128KB ] [ 区域B 64KB ] [ 区域C 32KB ]
|
|
|
↑ 不连续但heap_5能统一管理
|