内存基础知识

程序运行时,操作系统会为它分配一块内存空间,就像给工人分配一个工作台。这个内存空间主要分为四个区域:

  1. 代码区:存放程序指令的地方(相当于工作的说明书)
  2. 全局/静态区:存放全局变量和静态变量(相当于公共工具,大家都能用)
  3. 栈区(Stack):存放函数调用信息和局部变量(相当于私人工作台,用完就收)
  4. 堆区(Heap):存放动态分配的内存(相当于共享仓库,需要时自己去拿)

生活小比喻

想象你正在快餐店点餐:

  • 就像服务员按顺序叠放的点餐单(后点的餐单放在最上面,先处理最上面的)
  • 就像餐厅的储藏室,厨师可以随时去拿需要的食材

栈(Stack)操作详解

什么是栈?

栈是一种后进先出(LIFO)的数据结构,就像叠盘子:最后放上去的盘子总是最先被取走。

栈的基本操作

  • 压栈(Push):把数据放入栈顶(把盘子叠上去)
  • 出栈(Pop):从栈顶取出数据(取走最上面的盘子)

程序如何使用栈?

当我们调用一个函数时,程序会:

  1. 将函数参数压入栈中
  2. 将返回地址(调用后继续执行的位置)压入栈中
  3. 为函数的局部变量分配空间(也在栈上)
// 示例代码:函数调用时的栈操作 void functionA(int x) { int y = x + 5; // 局部变量y在栈上分配 functionB(y); } void functionB(int z) { // 当调用functionB时,栈中会有: // [返回地址][z参数][局部变量…] }

函数返回时栈的变化

当函数执行完毕返回时:

  1. 函数的局部变量被销毁(占用的栈空间被释放)
  2. 返回地址被弹出,程序回到调用位置继续执行
  3. 调用函数的参数被弹出

堆(Heap)操作详解

什么是堆?

堆是程序运行时可以动态申请内存的区域,就像一个大仓库:

  • 需要时才去申请空间
  • 用完后需要主动归还
  • 空间分配相对灵活

堆的基本操作(以C/C++为例)

  • 申请内存:使用malloc()或new关键字
  • 释放内存:使用free()或delete关键字
// 堆内存使用示例 int main() { // 在堆上分配一个整数(4字节) int* num = (int*)malloc(sizeof(int)); *num = 42; // 使用这块内存 // 使用完后释放内存 free(num); return 0; }

栈 vs 堆 对比

栈(Stack)

  • 自动管理:系统自动分配和释放
  • 大小固定:通常较小(几MB)
  • 速度快:只是移动栈指针
  • 局部变量:存储函数调用上下文
  • 后进先出(LIFO)

堆(Heap)

  • 手动管理:需程序员分配和释放
  • 大小灵活:受系统可用内存限制
  • 速度慢:需要查找可用内存块
  • 动态数据:存储需要长期存在的数据
  • 任意访问

堆栈溢出

栈溢出:当栈空间不足时发生,常见于:

  • 无限递归调用(函数不断调用自己)
  • 在栈上分配过大数组

堆溢出:当堆空间不足时发生,常见于:

  • 程序申请过多内存未释放(内存泄漏)
  • 申请过大的内存块

堆栈内存可视化