我对exe堆栈的位置感到有点困惑。我知道程序运行之前的CRT通过分配一定量的堆来初始化堆(堆由堆分配页面的操作系统分配),但堆栈在哪里?它也在页面上吗?或者通过在GDT上使用ring3描述符来共享用户模式(ring3)中的所有程序(我想不是,但我不确定)?
答案 0 :(得分:5)
Windows将为每个线程保留一个连续的虚拟内存区域(默认为1MB)。然后,它会提交该内存区域的几个最顶层的页面,并将其作为保护页面标记为一对。当线程的堆栈向下增长时,如果访问一个防护页面,则会发生异常并且Windows提交防护页面并将该页面下方的页面标记为防护。
您可以使用优秀的SysInternals实用程序VMMap来探索此行为。以下是该工具的摘录:
答案 1 :(得分:3)
每个线程都有自己的堆栈。它只是为此目的分配的一块内存。
所有内存都分配在页面中,包括堆栈(在Windows上,我相信堆栈默认为1MB,所以它会跨越多个页面,因为大多数内存页面都是4KB。)
但它实际上只是堆栈指针寄存器指向的一块内存。
答案 2 :(得分:1)
Windows中的每个程序都是一个过程。流程通常不会彼此分享他们的记忆。
共享和不共享是每个进程的虚拟地址空间如何映射到物理内存的问题。
如果两个进程将其地址空间的一部分映射到物理内存的相同页面,那么它们将有效地共享该内存,并且每个进程都可以读取并可能写入它并观察其他进程的写入。
共享堆栈内存没什么意义,因此每个进程都有自己的堆栈。实际上,流程更像是容器。执行代码并使用堆栈的实体是线程。每个过程中至少有一个线程。线程有自己的堆栈,但由于进程的线程在同一个虚拟地址空间,因此它们可以访问其他堆栈。有时在线程之间共享堆栈数据很有用,但应该小心处理,以免破坏线程状态并导致挂起或崩溃。