什么是栈和堆?
它们在计算机内存中物理上位于哪里?
在多大程度上由操作系统或语言运行时控制?
它们的作用域是什么?
什么决定了它们的大小?
什么使一个更快?
栈是什么以及它们在计算机内存中的位置?
当一个函数被调用时,栈的顶部会预留一块空间用于局部变量和一些数据记录。当该函数返回时,该块变为未使用状态,可以在下一次函数调用时再次使用。栈总是以后进先出(LIFO)的顺序保留;最近保留的块始终是下一个要释放的块。这使得跟踪栈非常简单;从栈中释放一个块只不过是调整一个指针。
堆是为动态分配而设置的内存。与栈不同,从堆中分配和释放块没有强制执行的模式;可以随时分配一个块,并随时释放它。这使得跟踪堆在任何给定时间哪些部分已分配或未分配变得非常复杂;有许多自定义堆分配器可用于为不同的使用模式调整堆性能。
每个线程都有一个栈,而应用程序通常只有一个堆(尽管有多个堆来处理不同类型的分配的情况并不少见)。
直接回答您的问题:
它们在多大程度上受到操作系统或语言运行时的控制?
操作系统在创建系统级线程时为每个线程分配栈。通常,操作系统由语言运行时调用来为应用程序分配堆。
它们的范围是什么?
栈附加到线程上,因此当线程退出时,栈将被回收。堆通常在应用程序启动时由运行时分配,并在应用程序(实际上是进程)退出时回收。
什么决定了它们的大小?
栈的大小在创建线程时设置。堆的大小在应用程序启动时设置,但可以根据需要增长(分配器向操作系统请求更多内存)。
什么使一个更快?
栈更快,因为访问模式使得从其中分配和释放内存非常简单(只需简单地增加或减少指针/整数),而堆则涉及更复杂的内存记录和分配/释放操作。此外,栈中的每个字节往往被频繁重用,这意味着它往往映射到处理器的缓存中,使其非常快。堆的另一个性能问题是,由于堆主要是全局资源,通常需要是多线程安全的,即每次分配和释放通常需要与程序中的“所有”其他堆访问同步。
一个清晰的演示:
!Image source: vikashazrati.wordpress.com