举个栗子

好读书,不求甚解

The Stack

什么是堆栈?它是计算机内存中的一个特殊区域,存储着被函数(包括main()函数)创建的临时变量。它由CPU非常紧密的管理和优化,是一种LIFO(后进先出)的数据结构。函数每一次定义一个新的变量,它都会被放进堆栈中。当函数执行完成退出时,被这个函数放到堆栈里的变量都会被释放,也就是从堆栈中被删除。一旦堆栈变量被释放,对于其他的堆栈变量而言,这个特殊的内存区域就变的可用。

使用堆栈来存储变量的好处是内存是由系统来管理,你不必手动的分配和释放内存。更重要的是,CPU管理堆栈内存非常的高效,从里面读写变量都是非常快速的。

对于堆栈还有一个要注意的地方,堆栈是有小大限制的,并且随着底层操作系统的不同,这个大小也是不同的。

总结一下:

  • 堆栈占用的大小会随着函数push和pop局部变量而增加和减小
  • 堆栈内存不需要自己手动管理,它的分配和释放都是自动
  • 堆栈有大小限制
  • 堆栈变量仅在创建它们的函数运行时存在

The Heap

堆是计算机内存中不会自动为您管理的区域,并且不受CPU严格管理。它是内存中更自由浮动的区域(并且更大)。要在堆上分配内存,必须使用内置的C函数malloc()calloc()。在堆上分配内存后,一旦不再需要,要使用free()释放该内存。如果不这样做,程序将发生所谓的内存泄漏,也就是说,堆上的内存仍将被保留(并且其他进程将无法使用)。

与堆栈不同,堆对变量大小没有限制(除了计算机物理内存限制以外)。相比于堆栈,堆内存的读写要稍慢一些,因为必须使用指针来访问堆上的内存数据。

还有一点和堆栈不同的是,在堆上创建的变量可以在程序中任何位置的任何函数访问。堆变量本质上是全局的。

利弊之分

Stack

  • 非常快的访问速度
  • 不必显示的取消分配的变量
  • 内存空间由CPU高效的管理,因而不会变的碎片化
  • 只能局部变量
  • 变量不能调整大小

Heap

  • 变量可以被全局访问
  • 没有内存大小的限制
  • 访问速度相对于堆栈要慢一些
  • 无法保证有效利用空间,随着时间的推移,内存块可能会随着内存块的分配而碎片化,然后释放
  • 必须手动的管理内存(分配和释放)
  • 变量可以使用realloc()调整大小

如何使用?

什么时候应该使用堆,什么时候应该使用堆栈?

如果您需要分配一个大的内存块(例如,一个大array或一个大的struct),并且需要长时间保持该变量(例如全局变量),则应该在堆上分配它。如果您要处理的变量相对较小,并且只要使用它们的函数时使用,那么您应该使用堆栈,它更容易,更快捷。如果您需要像数组和结构这样的变量可以动态更改大小(例如,可以根据需要增加或缩小的数组),则可能需要在堆上分配它们,并使用动态内存分配函数,如malloc()calloc()realloc()free()来“手动“管理该内存。

本文作者 : Kevalin
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://kevalin.github.io/2019/11/13/Stack-vs-Heap/