一、先铺垫程序运行时的 RAM 分区CPU 运行程序时操作系统会给进程分配一块物理 RAM并虚拟划分为 5 大区域地址从低到高代码段 (.text)存放编译好的程序二进制指令只读全局 / 静态区 (.data/.bss)全局变量、static 静态变量程序启动分配、结束释放栈 Stack高地址向下增长自动管理内存堆 Heap低地址向上增长手动管理内存内核共享区系统调用、动态库等不用细管核心一句话栈是系统自动分配释放的临时内存堆是程序员手动申请释放的自由大块 RAM二、栈 Stack栈内存在 RAM 高位1. 内存分配主体操作系统自动管理完全不用程序员操作每调用一个函数OS 就会在 RAM 栈区开辟一块栈帧函数执行完立刻自动回收这块 RAM无需手动释放。2. 存储什么全部临时数据函数局部变量、函数形参函数返回地址、寄存器临时备份常量数组、结构体定义在函数内部无 malloc3. RAM 栈核心特性大小固定、容量极小栈的总大小编译 / 系统限定Windows 默认 1MBLinux 8MBRAM 栈空间很小不能存超大数组否则栈溢出崩溃。地址从高向低增长新函数栈帧占用更低地址后进先出 LIFO 结构。分配释放极快仅移动栈指针 SP 寄存器只改一个地址值不用操作系统内核介入速度接近寄存器。生命周期绑定函数函数执行完毕这块 RAM 直接还给栈变量立刻失效数据销毁。栈示例代码 (C 语言)void func() { int a 10; // a存RAM栈 char buf[1024]; // 数组全部存在栈RAM } int main(){ func(); // 调用func开辟栈帧函数结束a、buf占用的RAM瞬间回收 return 0; }栈常见坑void test(){ char big[1024*1024*10]; // 10MB数组远超栈RAM上限 → 栈溢出程序崩溃 }三、堆 Heap堆内存RAM 中间自由区域1. 内存分配主体程序员手动控制操作系统仅提供 RAM 块堆是 RAM 中独立、超大、自由的内存池必须通过malloc/calloc/realloc向系统申请 RAM用完必须free归还否则永久占用 RAM内存泄漏。2. 存储什么malloc/new 动态申请的数组、大缓冲区、动态结构体、链表节点运行时才确定大小的数据编译期不知道占用多少 RAM3. RAM 堆核心特性容量巨大几乎占用剩余全部空闲 RAM没有栈那种几 MB 硬性限制适合存图片、大缓存、海量数据。地址从低向高增长每次 malloc 找堆中空闲 RAM 块分配内存地址不连续会产生内存碎片。分配释放慢调用堆管理器、内核申请 RAM涉及内存块查找、合并碎片远慢于栈。生命周期完全自主只要不 free哪怕函数执行结束这块堆 RAM 依然存在全局可访问手动 free 后才归还操作系统 RAM。堆示例代码 (C 语言)void func() { // 在堆RAM申请10KB内存指针p存在栈真正的数据存在堆 char *p (char*)malloc(1024*10); if(p NULL) return; // RAM不足分配失败 } int main(){ func(); // 函数func执行完栈里的p变量销毁但堆上10KB RAM没有释放 → 内存泄漏 return 0; }正确写法用完必须 free释放堆 RAMfree(p); // 把这块RAM交还给堆管理器 p NULL;堆常见问题内存泄漏malloc 不 freeRAM 长期占用程序越跑越卡野指针free 后继续使用指针访问已归还的 RAM程序崩溃内存碎片频繁 malloc/free堆 RAM 被分割成大量小块大块内存申请失败四、RAM 视角栈 vs 堆 直观对比表对比维度栈Stack RAM堆Heap RAMRAM 位置进程虚拟地址高位全局区下方、栈下方中间区域内存管理者操作系统自动管理程序员手动 malloc/free内存大小极小固定上限 (1M/8M)极大可用整机空闲 RAM分配速度极快仅移动栈指针较慢堆管理器、系统调用数据生命周期函数结束自动释放 RAM手动 free 才释放全局存活存储数据局部变量、小数组、形参动态缓冲区、大数据、链表 / 结构体内存连续性栈帧连续无碎片频繁分配会产生 RAM 内存碎片内存错误栈溢出超大局部数组内存泄漏、野指针、堆破坏五、经典示意图RAM 地址从上到下高地址 ─────────────────────── 栈Stack ↓向下增长 ↓ 空闲内存 ↑ 堆Heap ↑向上增长 全局/静态区 代码段 低地址 ───────────────────────六、一个完整例子看懂同一段代码里两块 RAM 分工#include stdlib.h void demo(){ // 1. num 变量本身存【栈RAM】仅4字节 int num 100; // 2. ptr指针存【栈RAM】8字节地址 // malloc申请的1000字节数据本体存在【堆RAM】 char *ptr (char*)malloc(1000); // 使用堆内存 ptr[0] A; // 释放堆RAM否则这块1000字节RAM永久占用 free(ptr); ptr NULL; } int main(){ demo(); // demo函数结束栈上num、ptr占用的RAM自动回收 // 若没写free堆上1000字节RAM不会回收造成泄漏 return 0; }关键点总结所有不带 malloc 的局部变量全部占用栈 RAM系统自动清理malloc/new申请的数据本体全部存堆 RAM必须手动释放存放堆地址的指针变量依然存在栈 RAM 里。