原文
What and where are the stack and heap?
译文
问
编程语言书籍解释了在堆栈上创建了值类型,并且在堆上创建了引用类型,而没有解释这两者是什么。 我还没有看到对此的明确解释。 我理解堆栈是什么。 但,
- 它们在哪里(物理上在真实计算机内存中)?
- 它们在多大程度上受操作系统或语言运行时控制?
- 它们的范围是什么?
- 是什么决定了它们的大小?
- 哪一个更快?
答(7K 多赞)
栈是作为执行线程的临时空间留出的内存。调用函数时,在栈顶部保留一个块,用于本地变量和一些临时数据。当该函数返回时,该块将变为未使用状态,并可在下次调用函数时使用。堆栈始终以 LIFO (后进先出)顺序保留;最近保留的块始终是要释放的下一个块。这使得跟踪栈非常简单;从栈中释放块只不过是调整一个指针。
堆是为动态分配留出的内存。与栈不同,堆中的块的分配和释放没有强制模式;您可以随时分配一个块并随时释放它。这使得在任何给定时间跟踪堆的哪些部分被分配或释放变得更加复杂;有许多自定义堆分配器可用于调整不同使用模式的堆性能。
每个线程都有一个栈,而应用程序通常只有一个堆(尽管为不同类型的分配设置多个堆并不罕见)。
直接回答您的问题:
- 它们在多大程度上受操作系统或语言运行时控制?
操作系统在创建线程时为每个系统级线程分配堆栈。 通常,语言运行库调用OS来为应用程序分配堆。
- 它们的范围是什么?
堆栈附加到一个线程,因此当线程退出堆栈时将被回收。 堆通常在应用程序启动时由运行时分配,并在应用程序(技术过程)退出时回收。
- 是什么决定了它们的大小?
创建线程时设置堆栈的大小。 堆的大小在应用程序启动时设置,但可以在需要空间时增长(分配器从操作系统请求更多内存)。
- 哪一个更快?
栈更快,因为访问模式使得从中分配和释放内存变得微不足道(指针/整数简单地递增或递减),而堆在分配或释放中涉及更复杂的临时数据保存。 此外,栈中的每个字节都经常被频繁地重用,这意味着它往往被映射到处理器的缓存,使其非常快。 堆的另一个性能损失是堆(主要是全局资源)通常必须是多线程安全的,即每个分配和释放都需要需要与程序中的“所有”其他堆访问代表性地同步。