栈内存是否是连续的?

22 浏览
0 Comments

栈内存是否是连续的?

编译器是如何强制栈内存连续的?它是在程序运行时每次都移动内存,还是在运行程序之前就预留程序所需的栈内存?

0
0 Comments

“堆栈内存是否是连续的?”这个问题的出现是因为堆栈和堆的性质不同。堆栈是紧凑的,没有空洞,因为堆栈中的所有内容都是被调用的函数的上下文。每当一个函数退出,它的上下文就会从堆栈的顶部被移除,我们回到之前的函数。相反,堆不像堆栈那样规整,当我们在堆中分配内存时,可能会创建空洞。我们可能在堆的某个位置分配4个字节的内存,然后再分配4个字节的内存,此时我们就会有从该位置起连续分配了8个字节的内存。但是这些内存可能在程序的任何时刻被释放,从而创建一个空洞。

在地址空间中,内核维护了一个表,将地址空间的页面映射到实际内存中的页面。当有多个程序运行时,不可能像上文描述的那样设置好所有东西。所以内核让每个进程认为整个地址空间是连续的内存,即使在内存中可能是非连续映射的(暂时不考虑内存映射设备)。

如果你对这个问题感兴趣,希望得到更详细的了解,我希望我给出了一个合理的概述,但可能有更好的作者,你可能更喜欢阅读他们的文章。所以你可以找一些关于虚拟内存的资料,这可能是你了解你想要的东西的一个很好的起点。有几本我知道的书会以更大或更小的细节来描述它,例如:《结构化计算机组织》(Structured computer organization) by tanenbaum;《操作系统概念》(Operating System Concept) by Silberschatz。我相信Knuth也在他的算法书中讨论过这个问题。如果你感到有冒险精神,你可以阅读英特尔手册中关于x86实现的部分。

0
0 Comments

根据以上内容,我们可以得出“Is stack memory contiguous?”这个问题的出现原因是因为有人质疑堆栈内存是否需要连续。在语言、操作系统或硬件层面上,并没有对堆栈需要连续的要求。尽管很多实现会使用连续内存,因为这样更简单,而且这也是计算机科学中教授堆栈概念的方式(堆栈向下增长,堆向上扩展)。但是,并没有对此有明确的要求。据说微软甚至尝试将堆栈帧放在堆的随机位置,以防止使用故意的栈溢出攻击技术。

堆栈的唯一要求是帧之间需要链接,这样可以在进入/离开作用域时推入/弹出帧。

编译器不会强制堆栈在内存中连续。在语言层面上并没有对堆栈需要连续的要求。

堆栈通常是如何实现的?如果这是问题的关键,那么你可以从社区得到更详细和准确的答案。

在之前的讨论中,某些情况下操作系统可以控制堆栈,而不是用户模式代码。但是,这并不意味着堆栈必须连续。操作系统供应商对堆栈实现可以施加任意限制,包括但不限于连续堆栈的效率。

总之,堆栈是否连续并没有明确的要求,但实际上许多实现会选择使用连续内存。

0
0 Comments

根据以上内容,我们可以得出以下结论:在Linux和类似系统中,线程的堆栈在虚拟内存中通常是连续的。然而,在Windows Vista及以上版本的Windows内核和z/OS中,堆栈可以在虚拟内存中是非连续的。GCC 4.6也允许非连续的堆栈。即使对于那些在虚拟内存中具有非连续地址的系统,编译器也不需要移动堆栈,它们只需要改变新部分的分配位置。然而,操作系统可能会将物理页面重新映射到虚拟页面,因此即使在虚拟内存中堆栈是连续的,它在物理内存中可能是非连续的。

但是,在Windows中,除了通过触发(连续的)保护页之外,没有任何其他方式可以扩展堆栈。因此,堆栈的连续性在Windows中是一个要求。而在Linux中,GCC 4.6及以后的版本支持非连续堆栈。在z/OS中,用户代码使用非连续堆栈。因此,我们不能绝对地说堆栈是否连续。

总之,堆栈是否连续在不同的操作系统和编译器中有不同的实现和要求。对于大多数情况来说,堆栈是否连续并不是一个必要的要求,但在某些情况下,堆栈的连续性可能是一个必要条件。

0