一句话:"栈是托盘,堆是仓库;托盘不乱,仓库会乱。"
栈是"一摞托盘"——后进先出,精确回收;堆是"自由仓库"——随意存取,东拼西凑。管理方式决定了速度、大小、碎片的一切差异。
deep(10000) 每层压帧 → 栈耗尽 → 栈溢出| 维度 | 栈 | 堆 |
|---|---|---|
| 谁分配 | 系统(函数调用) | 程序员(malloc) |
| 谁回收 | 系统自动 | 程序员(free) |
| 速度 | 快(移 SP 一条指令) | 慢(搜索空闲块) |
| 大小 | 小(KB 级,编译期定) | 大(受 RAM 总量限制) |
| 碎片 | 无(LIFO 精确回收) | 有(随机分配留洞) |
| 生命周期 | 函数调用期间 | malloc → free |
| 增长方向 | 高地址向下 | 低地址向上 |
| 溢出后果 | 栈溢出 → HardFault | 堆耗尽/碎片 → malloc 返回 NULL |
void deep(int n){ if(n) deep(n-1); } deep(10000) → 主要消耗栈,可能栈溢出(每层压帧)char pool[1024]; → 静态区,既不是栈也不是堆(大数组 ≠ 堆)uxTaskGetStackHighWaterMark()(创建任务时栈填已知模式,调度器定期检查剩多少)和 configCHECK_FOR_STACK_OVERFLOW + vApplicationStackOverflowHook();裸机用调试器看 SP / 栈填充模式扫描| 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 |
|---|---|---|
| 内存碎片 | 堆碎片专门深挖:怎么产生、怎么治 | 以为栈也碎片 |
| RTOS 栈估算 | HighWaterMark 检测栈剩余;栈大小按 word 配 | 以为栈溢出只能等崩溃 |
| 内存池 | 固定大小块 → 无碎片 + 分配确定 | 以为池子只是"省内存" |
| 内存分配方式 | 三区里的两个动态区,本题是它们的深度对比 | 把"大数组"当堆(静态区!) |
2026-08-03
每主题一页,复习时只翻本目录。