我目前正在学习包括内存在内的低级 arduino 内容。我的问题是,由于堆和堆栈在内存的另一侧增长,内存不足只有在两者都在中间的某个地方相遇时才会发生,或者当它们中的一个撞到中间时才会发生。
2 回答
- 没有“中间”的概念
- 取决于底层操作系统(如果有的话!)如何管理进程(如果平台上有这样的东西!),堆栈可能有一个有限的大小,比“整个内存的其余部分”小得多
- 取决于底层操作系统(如果有的话!)如何管理虚拟内存空间(如果平台上有这样的东西!),堆可能有一个有限的大小,比“整个内存的其余部分”小得多
如果这些限制中的任何一个到位,那么这些区域彼此相遇的可能性非常小。实际上,他们很可能很快就会用完空间,并且保护机制会引发相关的硬件软件异常。
这意味着“内存不足”事件不是一回事。堆栈中有OOM,堆中有OOM。在我所在的地区,传统上,与堆栈相关的称为 StackOverflow :),与堆相关的称为 OutOf[Heap]Memory。
值得注意的是,如果您的平台有虚拟内存的概念,那么堆栈很可能仍然是一个单一的空间块,但堆 - 可能是一个稀疏结构,并且将由多个分散的空间块组成,不一定在物理上按顺序排列某种上升或下降的方式。在这种情况下,很难谈论任何符合任何事情的事情。StackOverflow 发生在堆栈达到大小限制时,而 OutOfMemory 发生在内存管理器在内存空间中找不到合适的空闲孔时。
如果忽略虚拟内存,并且只谈论“原始硬件”,那么它取决于..堆栈的实际位置。IIRC(!),在一些(非常旧的)平台上,堆栈被预先分配在位于物理内存开头的一些预定义空间,比如说前十页,并增长到“底部”。然后是几页硬件映射表和端口状态图像,然后剩下的尾部是堆。通过这样的设置,当堆栈指针达到零时StackOverflow 上升。它非常“聪明”,因为使用处理器的状态标志很容易检测到零。此外,对于那些旧处理器来说,访问低地址比访问高地址要容易得多,因此将经常访问的堆栈放在低地址是一个很大的优势.
IIRC(!),较新的平台没有这些问题(通常,让我们忽略 NUMA 和类似的东西),并且当前传统的“原始硬件”设置将特殊区域(表、端口映射等)放在空间的开头,然后是堆,然后是“空闲区域”,然后是堆栈,堆栈溢出发生在空闲区域消失时,即堆栈遇到堆中已经存在的任何块时。请注意,StackOverflow 仍然不意味着 OutOfMemory:堆栈可能已经溢出,但堆可能有一些间隙并且仍然可能有很多可用空间!
请注意,那些“IIRC”很重要。我不是 Arduino 和当前处理器架构方面的专家,而且上面的“历史”之类的东西可能与新/旧的东西完全不同。我给它80%的概率是真的。