C++ 为什么堆栈内存大小如此有限?

C++ 为什么堆栈内存大小如此有限?,c++,memory-management,C++,Memory Management,在堆上分配内存时,唯一的限制是可用RAM(或虚拟内存)。它产生了Gb的内存 那么为什么堆栈大小如此有限(大约1MB)?什么技术原因阻止您在堆栈上创建真正大的对象 更新:我的意图可能不清楚,我不想在堆栈上分配巨大的对象,也不需要更大的堆栈。这个问题纯粹是好奇。首先,堆栈是连续的,所以如果分配12MB,当您想要低于您创建的内容时,必须删除12MB。同时,移动物体变得更加困难。下面是一个现实世界的例子,可以让事情更容易理解: 假设你正在房间周围堆放箱子。哪个更容易管理: 把任何重量的箱子叠在一起,但

在堆上分配内存时,唯一的限制是可用RAM(或虚拟内存)。它产生了Gb的内存

那么为什么堆栈大小如此有限(大约1MB)?什么技术原因阻止您在堆栈上创建真正大的对象


更新:我的意图可能不清楚,我不想在堆栈上分配巨大的对象,也不需要更大的堆栈。这个问题纯粹是好奇。

首先,堆栈是连续的,所以如果分配12MB,当您想要低于您创建的内容时,必须删除12MB。同时,移动物体变得更加困难。下面是一个现实世界的例子,可以让事情更容易理解:

假设你正在房间周围堆放箱子。哪个更容易管理:

  • 把任何重量的箱子叠在一起,但当你需要在底部放东西时,你必须把整个箱子都解开。如果你想把一件物品从堆里拿出来交给其他人,你必须把所有的盒子都拿下来,然后把盒子移到其他人的堆里(仅堆叠)
  • 你把所有的盒子(除了非常小的盒子)放在一个特殊的区域,在那里你不会把东西堆在其他东西的上面,写下你放在纸上的地方(指针),然后把纸放在纸堆上。如果你需要把盒子交给其他人,你可以把你那堆纸中的纸条递给他们,或者给他们一份复印件,把原件留在你那堆纸里。(堆栈+堆)

这两个例子都是粗略的概括,在类比中有一些观点显然是错误的,但它非常接近,希望能帮助你看到这两种情况的优点。

我的直觉如下。堆栈不像堆那么容易管理。堆栈需要存储在连续的内存位置。这意味着您不能根据需要随机分配堆栈,但至少需要为此保留虚拟地址。保留的虚拟地址空间越大,可以创建的线程就越少

例如,32位应用程序的虚拟地址空间通常为2GB。这意味着,如果堆栈大小为2MB(在pthreads中为默认值),则最多可以创建1024个线程。对于web服务器等应用程序来说,这可能很小。将堆栈大小增加到(比如)100MB(即,您保留100MB,但不一定立即将100MB分配给堆栈)会将线程数量限制在20个左右,即使对于简单的GUI应用程序也是如此


一个有趣的问题是,为什么我们在64位平台上仍然有这个限制。我不知道答案,但我假设人们已经习惯了一些“堆栈最佳实践”:小心在堆上分配巨大的对象,如果需要,手动增加堆栈大小。因此,没有人发现在64位平台上添加“巨大”堆栈支持是有用的。

这只是一个默认大小。如果你需要更多,你可以得到更多——通常是告诉链接器分配额外的堆栈空间

拥有大堆栈的缺点是,如果创建多个线程,则每个线程将需要一个堆栈。如果所有堆栈都分配多MB,但不使用它,那么空间将被浪费

你必须为你的计划找到适当的平衡


有些人,比如@BJovke,认为虚拟内存本质上是免费的。的确,不需要物理内存来支持所有虚拟内存。您必须至少能够向虚拟内存提供地址

然而,在一台典型的32位PC上,虚拟内存的大小与物理内存的大小相同,因为我们只有32位的地址,不管是虚拟地址还是非虚拟地址


因为一个进程中的所有线程共享相同的地址空间,所以它们必须在它们之间分配地址空间。在操作系统参与进来之后,应用程序“只剩下”2-3 GB。这个大小是物理内存和虚拟内存的限制,因为没有更多的地址了。

我不认为有任何技术原因,但这将是一个奇怪的应用程序,它只在堆栈上创建了一个巨大的超级对象。堆栈对象缺乏灵活性,随着大小的增加,问题会变得更加严重-如果不销毁它们,就无法返回,也无法将它们排入其他线程的队列。

请按照从近到远的顺序考虑堆栈。寄存器靠近CPU(速度快),堆栈稍微远一点(但仍然相对较近),堆离CPU较远(访问速度慢)

堆栈当然存在于堆上,但由于它一直在使用,它可能永远不会离开CPU缓存,这使得它比平均堆访问速度更快。 这是保持堆栈大小合理的原因;尽可能多地缓存它。分配大堆栈对象(可能会在溢出时自动调整堆栈大小)违背了这一原则


因此,这是一个很好的性能范例,而不仅仅是旧时代的遗留物。

一个还没有人提到的方面:

有限的堆栈大小是一种错误检测和遏制机制。

一般来说,C和C++中堆栈的主要工作是跟踪调用堆栈和局部变量,如果堆栈超出界限,设计和/或应用程序的行为几乎总是错误。
如果允许堆栈任意增长,这些错误(如无限递归)将在操作系统资源耗尽后很晚被捕获。可以通过对堆栈大小设置任意限制来防止这种情况。除了足够小以防止系统降级之外,实际大小并不重要。

许多您认为需要大堆栈的事情可以通过其他方式完成

塞吉威克的“算法”