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