und*_*ndu 73 c++ memory-management
在堆上分配内存时,唯一的限制是可用RAM(或虚拟内存).它使Gb成为记忆.
那么为什么堆栈大小如此有限(约1 Mb)?什么技术原因阻止你在堆栈上创建真正的大对象?
更新:我的意图可能不明确,我不想在堆栈上分配大对象,我不需要更大的堆栈.这个问题只是纯粹的好奇心.
use*_*136 40
我的直觉如下.堆栈不像堆那样容易管理.堆栈需要存储在连续的存储器位置.这意味着您无法根据需要随机分配堆栈,但您需要至少为此目的保留虚拟地址.保留的虚拟地址空间的大小越大,您可以创建的线程越少.
例如,32位应用程序通常具有2GB的虚拟地址空间.这意味着如果堆栈大小为2MB(在pthreads中为默认值),则可以创建最多1024个线程.对于Web服务器等应用程序而言,这可能很小.将堆栈大小增加到100MB(即,您保留100MB,但不一定要立即为堆栈分配100MB),会将线程数限制为大约20,这对于简单的GUI应用程序来说可能是有限的.
一个有趣的问题是,为什么我们仍然在64位平台上有这个限制.我不知道答案,但我认为人们已经习惯了一些"堆栈最佳实践":小心在堆上分配大对象,如果需要,手动增加堆栈大小.因此,没有人发现在64位平台上添加"巨大"的堆栈支持是有用的.
And*_*tin 26
尚未提及的一个方面:
有限的堆栈大小是错误检测和包含机制.
通常,C和C++中堆栈的主要工作是跟踪调用堆栈和局部变量,如果堆栈超出界限,则几乎总是设计和/或应用程序行为中的错误.
如果允许堆栈任意增大,那么只有在操作系统资源耗尽后才能很晚捕获这些错误(如无限递归).通过设置堆栈大小的任意限制来防止这种情况.实际尺寸并不重要,除了它足够小以防止系统退化.
Bo *_*son 14
它只是一个默认大小.如果您需要更多,您可以获得更多 - 通常是告诉链接器分配额外的堆栈空间.
拥有大型堆栈的缺点是,如果创建多个线程,则每个线程需要一个堆栈.如果所有堆栈都分配了多个MB,但没有使用它,则会浪费空间.
你必须找到适合你的程序的平衡.
像@BJovke这样的人认为虚拟内存基本上是免费的.确实,您不需要物理内存支持所有虚拟内存.您必须至少能够为虚拟内存分配地址.
但是,在典型的32位PC上,虚拟内存的大小与物理内存的大小相同 - 因为我们只有32位用于任何地址,虚拟或非虚拟.
因为进程中的所有线程共享相同的地址空间,所以它们必须在它们之间进行划分.在操作系统发挥作用之后,应用程序只剩下2-3 GB.这个大小对于极限两者的物理和虚拟内存,因为那里只是没有任何其它地址.
小智 7
按照从近到远的顺序考虑堆栈。寄存器靠近CPU(快),栈有点远(但仍然相对接近),堆远离(慢访问)。
堆栈当然存在于堆上,但是,由于它被连续使用,它可能永远不会离开 CPU 缓存,使其比普通堆访问更快。这是保持堆栈合理大小的一个原因;尽可能地保持缓存。分配大堆栈对象(可能会在溢出时自动调整堆栈大小)违背了这一原则。
因此,它是性能的一个很好的范例,而不仅仅是旧时代的遗留物。
一方面,堆栈是连续的,所以如果分配12MB,则当要低于所创建的内容时,必须删除12MB。而且,移动物体变得更加困难。这是一个真实的示例,可能会使事情更容易理解:
假设您在一个房间里堆放箱子。哪个更易于管理:
这两个例子是粗略的概括,在类比中有些地方公然是错误的,但它非常接近,希望可以帮助您看到这两种情况的优点。