文章

堆和栈

堆和栈

区别

项目栈(Stack)堆(Heap)
存储位置内存中的一块连续区域,由编译器自动分配与释放内存中的一块较大空间,由程序员手动申请与释放(如 new / delete
分配管理编译器自动管理程序员或运行库管理
生命周期当函数结束时自动释放直到显式释放或程序结束
存储内容局部变量、函数参数、返回地址等动态分配的对象或数组
存储响应只要栈的剩余空间足够就能申请,否则提示栈溢出系统从链表中找出一块空闲内存地址
申请速度和大小系统自动分配,速度较快,内存连续大小一半不超过8M由new分配,速度比较慢,内存不连续容易产生内存碎片,但是大小只受限于计算机系统中有效的虚拟内存

工作原理

栈(Stack)

  • 是一种先进后出(LIFO)的结构,或者说后进先出(FILO)
  • 每进入一个函数,就会在栈上分配空间
  • 函数返回后,该空间自动释放
1
2
3
void func() {
	int a = 10;	// 栈上分配
}	// 函数结束,a自动销毁

堆(Heap)

  • 通过动态分配(new,malloc)得到
  • 内存空间在使用后必须手动释放,否则会内存泄漏
1
2
3
4
void func() {
	int *p = new int(10);	// 堆上分配
	delete p;				// 手动释放
}

优缺点

方面
速度快(由CPU寄存器直接支持)慢(需要动态查找空闲块)
空间大小小(几MB)大(几百MB甚至GB)
分配/释放自动手动(或智能指针管理)
安全性高(自动释放)低(可能内存泄漏或野指针)

例子

1
2
3
4
5
6
7
8
9
void example() {
	int a = 5;				// 栈内存
	int *p = new int(5);	// 堆内存

	std::cout << &a << std::endl;	// 栈区地址,靠近高地址
	std::cout << p << std::endl;	// 堆区地址,靠近低地址

	delete p;				// 释放堆内存
}

通常情况下:

  • 栈区从高地址向低地址增长
  • 堆区从低地址向高地址增长
本文由作者按照 CC BY 4.0 进行授权