首页 > 解决方案 > 为什么我们限制堆栈的大小而不是内存中的堆

问题描述

我主要用 C++ 编程。我从很多地方看到我应该将大对象(如 10k 元素的数组)放在堆上(使用 new)而不是放在堆栈上(使用纯数组类型)。我真的不明白。原因可能是因为滥用堆栈很多导致运行时堆栈溢出错误。但是,为什么操作系统要为进程(或更准确地说,线程)的堆栈大小设置限制,因为虚拟内存可以根据需要(或实际上是 4G)变大。谁能帮帮我,我真的不知道。

标签: c++memorystack

解决方案


传统和线程。

堆栈是每个线程的,并且为了效率必须是连续的内存空间。不连续的堆栈使每个函数调用更加昂贵。

堆通常在线程之间共享;当它们不是时,它们不必是连续的。

在 32 位时代,拥有 1000 个线程并非不可能。每个线程 1 兆,即 1 GB 的地址空间。1兆也不是那么大。

相比之下,2 gigs 的堆服务于所有线程。

在 64 位系统上,通常可寻址内存远小于 64 位。在 40 位时,如果您将一半的地址空间分配给堆栈并且您有 10,000 个线程,那么每个堆栈只有 50 兆位。

48 位更常见,但每个堆栈仍然只有千兆字节的地址空间。

相比之下,堆有 tebibytes。

更重要的是,堆栈上的大对象对缓存一致性没有多大帮助。没有cpu缓存可以容纳tront和back。如果您大量使用它,则必须遵循单个指针是微不足道的,甚至可以确保堆栈更好地保持在缓存中。

因此(a)堆栈大小成本随线程而变化(b)地址空间可以受到限制(c)巨型堆栈的好处很小。

最后,无限递归是一个常见的错误。您希望在您的用户 shell 因资源耗尽而崩溃之前,您的堆栈被炸毁并陷入陷阱(二进制加载程序经常用陷阱页面包围堆栈)。适度大小的堆栈使这种可能性更大。


推荐阅读