【问题标题】:Stack on Windows - where is it?Windows 上的堆栈 - 它在哪里?
【发布时间】:2012-09-08 08:22:32
【问题描述】:

我对 exe 堆栈的位置有点困惑。我知道 CRT 在程序运行之前通过分配一定数量的堆来初始化堆(这又由分配页面的操作系统分配),但是堆栈在哪里?也是在页面上吗?还是通过在 GDT 上使用 ring3 描述符在用户模式 ​​(ring3) 中的所有程序共享它(我认为不是,但我不确定)?

【问题讨论】:

    标签: c++ c windows stack kernel


    【解决方案1】:

    Windows 将为每个线程保留一个连续的虚拟内存区域(默认为 1MB)。然后,它提交该内存区域的几个最顶层页面,并将其下方的几个标记为保护页面。随着线程堆栈向下增长,如果访问保护页面,则会发生异常,Windows 会提交保护页面并将其下方的页面标记为保护。

    您可以使用出色的SysInternals 实用程序VMMap 来探索这种行为。以下是该工具的 sn-p:

    【讨论】:

      【解决方案2】:

      每个线程都有自己的堆栈。它只是为此目的分配的一块内存。

      所有内存都在页面中分配,包括堆栈(在 Windows 上,我相信堆栈默认为 1MB,因此它会跨越多个页面,因为大多数内存页面都是 4KB。)

      但它实际上只是堆栈指针寄存器指向的一块内存。

      【讨论】:

      • 栈是在线程创建的时候初始化的,所以对于单线程的应用来说,主线程的栈是在应用启动的时候创建的,这个也是crt做的吗?
      • crt 做不到——它可能不是 C 程序!即使是这样,也必须在运行 crt 之前设置堆栈,否则 crt 将无法使用堆栈,即。它将无法使用任何自动变量、参数或进行任何函数调用。 Windows 操作系统加载程序设置初始堆栈,由 EXE/DLL/SYS/whatever PE 标头中的数据指示。
      【解决方案3】:

      Windows 中的每个程序都是一个进程。进程通常不会在彼此之间共享它们的记忆。

      共享与不共享是每个进程的虚拟地址空间如何映射到物理内存的问题。

      如果两个进程将其地址空间的一部分映射到物理内存的相同页面,则该内存由它们有效共享,并且每个进程都可以读取和可能写入它并观察另一个进程的写入。

      共享堆栈内存几乎没有意义,因此每个进程都有自己的堆栈。实际上,进程更像是容器。执行代码和使用堆栈的实体是线程。每个进程中至少有一个线程。线程有自己的栈,但由于一个进程的线程在同一个虚拟地址空间中,它们可以访问彼此的栈。有时在线程之间共享堆栈数据很有用,但应谨慎执行,以免破坏线程状态并导致挂起或崩溃。

      【讨论】:

        猜你喜欢
        • 2020-09-18
        • 2014-04-21
        • 2012-11-03
        • 1970-01-01
        • 2010-11-15
        • 1970-01-01
        • 2011-11-09
        • 2015-10-24
        • 2015-06-02
        相关资源
        最近更新 更多