c++ - 为什么我们限制堆栈的大小而不是内存中的堆
问题描述
我主要用 C++ 编程。我从很多地方看到我应该将大对象(如 10k 元素的数组)放在堆上(使用 new)而不是放在堆栈上(使用纯数组类型)。我真的不明白。原因可能是因为滥用堆栈很多导致运行时堆栈溢出错误。但是,为什么操作系统要为进程(或更准确地说,线程)的堆栈大小设置限制,因为虚拟内存可以根据需要(或实际上是 4G)变大。谁能帮帮我,我真的不知道。
解决方案
传统和线程。
堆栈是每个线程的,并且为了效率必须是连续的内存空间。不连续的堆栈使每个函数调用更加昂贵。
堆通常在线程之间共享;当它们不是时,它们不必是连续的。
在 32 位时代,拥有 1000 个线程并非不可能。每个线程 1 兆,即 1 GB 的地址空间。1兆也不是那么大。
相比之下,2 gigs 的堆服务于所有线程。
在 64 位系统上,通常可寻址内存远小于 64 位。在 40 位时,如果您将一半的地址空间分配给堆栈并且您有 10,000 个线程,那么每个堆栈只有 50 兆位。
48 位更常见,但每个堆栈仍然只有千兆字节的地址空间。
相比之下,堆有 tebibytes。
更重要的是,堆栈上的大对象对缓存一致性没有多大帮助。没有cpu缓存可以容纳tront和back。如果您大量使用它,则必须遵循单个指针是微不足道的,甚至可以确保堆栈更好地保持在缓存中。
因此(a)堆栈大小成本随线程而变化(b)地址空间可以受到限制(c)巨型堆栈的好处很小。
最后,无限递归是一个常见的错误。您希望在您的用户 shell 因资源耗尽而崩溃之前,您的堆栈被炸毁并陷入陷阱(二进制加载程序经常用陷阱页面包围堆栈)。适度大小的堆栈使这种可能性更大。
推荐阅读
- php - 解释这是什么意思:'post__not_in' => array($post->ID)
- laravel - DataTables - 在服务器端指定页面大小
- python - Python:在构建提取期间使用 osmnx 出错
- javascript - 使用Angular2+根据新选择的数字动态重新排列行
- python - 在python中同时循环两个for循环的问题
- php - PHP sendmail 不发送@RU 域电子邮件
- android - 如何修复此错误 java.lang.UnsupportedOperationException: This is not supported, use MenuItemCompat.setOnActionExpandListener()
- django - 如何在项目外使用脚本访问 django 模型
- json - 使用 python3 从 json 文件中获取数据。如何从数据池中打印特定部分?
- ansible - 需要在文本文件中添加行块