## 堆 vs 栈 ## 判别规则(核心,唯一要记的) - 一句话区分:**栈靠"后进先出"精确回收 → 快、小、无碎片、系统管;堆靠"随机分配"自由存取 → 慢、大、有碎片、程序员管** - 面试输出公式:**6 维对照(分配/回收/速度/大小/碎片/生命周期)+ 1 个为什么(栈为何不碎片)** 一句话:**"栈是托盘,堆是仓库;托盘不乱,仓库会乱。"** ## 抽象描述(一句话本质) 栈是"一摞托盘"——后进先出,精确回收;堆是"自由仓库"——随意存取,东拼西凑。管理方式决定了速度、大小、碎片的一切差异。 ## 正反例(建立直觉) - **正例1(分配)**:栈 = 移动 SP 指针,编译期算好偏移,一条指令;堆 = malloc 运行时搜索空闲链表,可能要分裂/合并 - **正例2(回收)**:栈 = 函数返回 SP 一拨,从顶往下收;堆 = free 手动,可能先释放中间的块 → 留空洞 - **正例3(碎片)**:栈 LIFO 精确回收永不碎片(一摞盘子从顶拿,中间永不留空);堆随机分配随机释放 → 中间留洞,洞太小塞不进新申请 → 碎片化 - **反例1**:深层递归 `deep(10000)` 每层压帧 → 栈耗尽 → 栈溢出 - **反例2**:反复 malloc/free **同大小块**不会碎片(原样复用)——这正是内存池防碎片的原理 ## 易混对比(8 维度) | 维度 | 栈 | 堆 | | -------- | ----------------------- | ------------------------------ | | 谁分配 | 系统(函数调用) | 程序员(malloc) | | 谁回收 | 系统自动 | 程序员(free) | | 速度 | 快(移 SP 一条指令) | 慢(搜索空闲块) | | 大小 | 小(KB 级,编译期定) | 大(受 RAM 总量限制) | | 碎片 | **无**(LIFO 精确回收) | **有**(随机分配留洞) | | 生命周期 | 函数调用期间 | malloc → free | | 增长方向 | 高地址向下 | 低地址向上 | | 溢出后果 | 栈溢出 → HardFault | 堆耗尽/碎片 → malloc 返回 NULL | ## 变体验证(3 题,全过=学会) 1. `void deep(int n){ if(n) deep(n-1); }` `deep(10000)` → 主要消耗**栈**,可能**栈溢出**(每层压帧) 2. 陷阱题:循环反复 malloc/free **同大小块** → **不会产生碎片**(free 的空闲块被下一个 malloc 原样复用) 3. 陷阱题:全局数组 `char pool[1024];` → **静态区**,既不是栈也不是堆(大数组 ≠ 堆) ## 口述要点(面试怎么讲) - **结论先行**:六维对比(分配/回收/速度/大小/碎片/生命周期),核心落点在"回收能否精确控制" - **为什么栈不碎片**:回收严格后进先出,永远从顶往底收,中间不可能留洞 - **嵌入式为什么用内存池**:① 固定大小块 → free 后任意新申请原样复用 → 无碎片 ② **分配快且时间确定**(直接拿一块,不搜索不合并)——第②点对实时系统是关键 - **栈溢出检测**:FreeRTOS 用 **`uxTaskGetStackHighWaterMark()`**(创建任务时栈填已知模式,调度器定期检查剩多少)和 `configCHECK_FOR_STACK_OVERFLOW` + `vApplicationStackOverflowHook()`;裸机用调试器看 SP / 栈填充模式扫描 - **碎片失败 vs 内存不够**:碎片失败**可解**(合并整理碎片后又能申请);真·内存不够**无解**(物理限制只能加内存) - **易错点**:以为栈也碎片;把大数组当堆(是静态区);递归深就是栈问题不是堆问题 ## 关系网络 | 相邻概念 | 和本主题的关系 | 孤立理解会犯的错 | | ------------ | ------------------------------------------ | -------------------------- | | 内存碎片 | 堆碎片专门深挖:怎么产生、怎么治 | 以为栈也碎片 | | RTOS 栈估算 | HighWaterMark 检测栈剩余;栈大小按 word 配 | 以为栈溢出只能等崩溃 | | 内存池 | 固定大小块 → 无碎片 + 分配确定 | 以为池子只是"省内存" | | 内存分配方式 | 三区里的两个动态区,本题是它们的深度对比 | 把"大数组"当堆(静态区!) | ## 学习日期 2026-08-03 --- _每主题一页,复习时只翻本目录。_