堆(Heap) 和栈(Stack) 是程序运行时内存管理的两个核心区域
,主要区别如下:
1. 内存分配方式
- 栈 :由编译器自动分配和释放,存储局部变量、函数参数、返回值等。内存分配效率高(仅移动栈指针)。
- 堆 :由开发者手动申请(如
malloc
、new
)和释放(如free
、delete
),用于存储动态分配的对象。分配需要查找可用内存块,效率较低。
2. 内存布局
- 栈 :内存空间连续 ,遵循后进先出(LIFO)原则。函数调用时生成栈帧,结束时销毁。
- 堆 :内存空间非连续,灵活但可能产生内存碎片。分配和释放顺序无固定规则。
3. 容量限制
- 栈 :大小固定(默认几MB,不同系统不同),容易发生栈溢出(如递归过深)。
- 堆:可用空间远大于栈(受系统虚拟内存限制),更适合存储大型数据。
4. 生命周期
- 栈:变量生命周期与所属函数一致,函数结束自动释放。
- 堆 :内存生命周期由开发者控制,未释放会导致内存泄漏。
5. 访问速度
- 栈:访问速度快(CPU 缓存优化,内存连续)。
- 堆:访问速度较慢(需通过指针间接访问,内存可能分散)。
6. 线程安全
- 栈 :每个线程独占自己的栈,无竞争问题。
- 堆 :多线程共享,需同步机制(如锁)避免冲突。
7. 典型问题
- 栈:栈溢出(Stack Overflow)、未初始化指针。
- 堆:内存泄漏(Memory Leak)、野指针、内存碎片。
代码示例
c
void func() {
int a = 10; // 栈上分配
int *p = (int*)malloc(sizeof(int)); // 堆上分配
*p = 20;
free(p); // 需手动释放堆内存
}
总结
- 栈:高效、自动管理,适合小型、短生命周期的数据。
- 堆 :灵活、手动管理,适合大型、长生命周期的动态数据。
正确使用两者对程序性能和稳定性至关重要。