【问题标题】:Why we limit the size of stack but not heap in memory [duplicate]为什么我们限制堆栈的大小而不是内存中的堆[重复]
【发布时间】:2020-10-02 17:21:27
【问题描述】:

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

【问题讨论】:

  • 没有一般限制。看看这个问题:stackoverflow.com/questions/1825964你为什么想要一个巨大的堆栈大小,你不应该需要它。递归并不常用,尤其是在堆栈中存储大量数据的情况下。
  • 但操作系统为什么要为进程的堆栈大小设置限制 在 32 位应用程序中,堆栈空间量限制了线程数你可以在 Windows 上创建。使用 1MB 堆栈,您可以在用完整个 2GB 用户地址空间之前创建大约 2000 个线程。
  • 这能回答你的问题吗? C/C++ maximum stack size of program
  • (使用新的) 在现代c++ 代码中不鼓励使用new。 std::vector 更合适。
  • 这是个好问题。但是以前有人问过;请阅读副本中的答案。

标签: c++ memory stack


【解决方案1】:

传统和线程。

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

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

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

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

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

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

相比之下,堆有 tebibytes。

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

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

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

【讨论】:

  • “堆栈必须是连续的内存空间”是限制堆栈大小和速度的一个很好的理由。谢谢。
【解决方案2】:

完全可以使用 10k 个 INT 的静态数组。通常最好使用“new”,因为当您处理大块数据时,您不能保证它们始终是数组的大小。内存的动态分配让你只使用你需要的东西。效率更高。

如果您对操作系统如何选择堆栈大小或“页面”感到好奇,请阅读以下内容: https://en.m.wikipedia.org/wiki/Page_(computer_memory)

另外,我不确定您是否以正确的方式使用“堆”。 “堆”是一种基于树的数据结构。 Stack指的是RAM中可执行文件和进程数据的布局。

【讨论】:

    猜你喜欢
    • 2011-10-02
    • 2012-09-23
    • 2022-07-21
    • 2012-05-16
    • 2014-01-19
    • 2011-06-25
    • 1970-01-01
    • 2010-12-05
    相关资源
    最近更新 更多