Operating system 堆栈能否增长到堆中?

Operating system 堆栈能否增长到堆中?,operating-system,heap-memory,stack-memory,Operating System,Heap Memory,Stack Memory,我目前正在学习操作系统,了解到堆栈位于内核和堆之间。让我困惑的是,在大多数实现中,由于堆栈倾向于向下增长,而堆增长到更高的内存地址,是什么阻止堆栈增长到堆中?如果有可能,如果它确实增长到堆中会发生什么?这不一定正确: 我目前正在学习操作系统,了解到堆栈位于内核和堆之间 堆栈和堆只是内存。除了如何使用外,它们无法区分。地址空间中可以有多个堆和多个堆栈 堆不能增长到堆栈中,反之亦然。操作系统将不允许堆重新分配已分配给堆栈的内存 人们可以访问堆栈末尾以外的内存,理论上,堆栈可能是堆的一部分。一些操作系

我目前正在学习操作系统,了解到堆栈位于内核和堆之间。让我困惑的是,在大多数实现中,由于堆栈倾向于向下增长,而堆增长到更高的内存地址,是什么阻止堆栈增长到堆中?如果有可能,如果它确实增长到堆中会发生什么?

这不一定正确:

我目前正在学习操作系统,了解到堆栈位于内核和堆之间

堆栈和堆只是内存。除了如何使用外,它们无法区分。地址空间中可以有多个堆和多个堆栈

堆不能增长到堆栈中,反之亦然。操作系统将不允许堆重新分配已分配给堆栈的内存


人们可以访问堆栈末尾以外的内存,理论上,堆栈可能是堆的一部分。一些操作系统在堆栈的末尾放置了不可访问的防护装置。

这不一定正确:

我目前正在学习操作系统,了解到堆栈位于内核和堆之间

堆栈和堆只是内存。除了如何使用外,它们无法区分。地址空间中可以有多个堆和多个堆栈

堆不能增长到堆栈中,反之亦然。操作系统将不允许堆重新分配已分配给堆栈的内存


人们可以访问堆栈末尾以外的内存,理论上,堆栈可能是堆的一部分。一些操作系统在堆栈的末尾放置了不可访问的防护装置。

传统上,内存的简化视图是这样的:

 ===================
| Operating System  | High memory
 ===================
|   Your program    |
|  ---------------  |
| | Process stack | |
|  ---------------  | Transient program area
| |  Process heap | |
|  ---------------  |
| |  Program code | |
|  ---------------  |
 ===================
| Operating system  | Low memory
 ===================
正如您所指出的,进程堆栈从操作系统代码的正下方开始,并向下增长。另一方面,进程堆从固定程序代码上方开始,然后向上增长

在PC操作系统的早期,这实际上是内存中程序的物理布局。例如,CP/M操作系统为某些操作系统引导代码保留了前256字节的内存,其余必要的操作系统服务占用了高内存区域。程序在地址0x0100处启动,可以使用从地址0x0100到顶部操作系统代码开始之间的所有内存。MS-DOS非常相似

没有护栏可以防止您提到的情况发生:程序会在堆栈上分配太多空间,以至于它会重写在堆上分配的内存。或者,程序会分配堆内存,以覆盖处理器堆栈。当这些事情发生时,程序就会崩溃。在某些情况下,操作系统也会崩溃。当然,因为一次只能运行一个程序,所以这不是什么大问题:只需重新启动机器,然后再试一次


现代计算机拥有更先进的内存布局,而这一概念已不再适用。今天的操作系统在执行内存访问限制方面可以做得更好。例如,为一个进程的堆栈分配一个固定段(通常为1M字节)。如果程序试图使用比分配的堆栈空间更多的堆栈空间,内存管理器将不允许这样做。程序将因访问冲突而崩溃。出于同样的原因,程序的堆不能增长到分配给堆栈的内存中。

内存的简化视图通常如下所示:

 ===================
| Operating System  | High memory
 ===================
|   Your program    |
|  ---------------  |
| | Process stack | |
|  ---------------  | Transient program area
| |  Process heap | |
|  ---------------  |
| |  Program code | |
|  ---------------  |
 ===================
| Operating system  | Low memory
 ===================
正如您所指出的,进程堆栈从操作系统代码的正下方开始,并向下增长。另一方面,进程堆从固定程序代码上方开始,然后向上增长

在PC操作系统的早期,这实际上是内存中程序的物理布局。例如,CP/M操作系统为某些操作系统引导代码保留了前256字节的内存,其余必要的操作系统服务占用了高内存区域。程序在地址0x0100处启动,可以使用从地址0x0100到顶部操作系统代码开始之间的所有内存。MS-DOS非常相似

没有护栏可以防止您提到的情况发生:程序会在堆栈上分配太多空间,以至于它会重写在堆上分配的内存。或者,程序会分配堆内存,以覆盖处理器堆栈。当这些事情发生时,程序就会崩溃。在某些情况下,操作系统也会崩溃。当然,因为一次只能运行一个程序,所以这不是什么大问题:只需重新启动机器,然后再试一次

现代计算机拥有更先进的内存布局,而这一概念已不再适用。今天的操作系统在执行内存访问限制方面可以做得更好。例如,为一个进程的堆栈分配一个固定段(通常为1M字节)。如果程序试图使用比分配的堆栈空间更多的堆栈空间,内存管理器将不允许这样做。程序将因访问冲突而崩溃。出于同样的原因,程序的堆不能增长到分配给堆栈的内存中。

运行到其他动态分配中的堆栈(或线程堆栈)被称为“堆栈冲突”,是的,这是一种真正的攻击类型,尤其是对于潜在的巨大未检查
alloca()
或VLA。特别是因为线程堆栈与其他动态分配混合在一起。有更多关于现代机制的信息来加强对此类错误的防御,同时运行到其他动态分配中的堆栈(或线程堆栈)也被称为“堆栈冲突”,是的,这是一种真正的攻击类型,特别是对于潜在的巨大未经检查的
alloca()
或VLA。尤其是因为线程堆栈