代码之家  ›  专栏  ›  技术社区  ›  Konstantin Burlachenko

在本地变量未初始化的情况下,Windows线程堆栈保护页机制如何工作?

  •  4
  • Konstantin Burlachenko  · 技术社区  · 10 年前

    在用于x86-32/x86-64体系结构的Windows操作系统上,线程堆栈虚拟内存由“保留部分”、“提交部分”和“保护页”组成。

    问题:

    假设我有1页提交内存,1MB的线程堆栈保留内存。 在没有初始化的情况下,我在堆栈上分配了相当于K页的内存。K例如等于10。似乎在堆栈开始时,堆栈上的帧内存将由用户空间代码分配,如下所示:

    sub esp, K*4096
    

    当存在对保护页的读/写请求时,保护页机制工作。

    但是,我将对超出此保护页的某些内存执行读/写操作,这将是什么呢?

    2 回复  |  直到 5 年前
        1
  •  4
  •   Hans Passant    10 年前

    您通常开始测试启用了运行时检查的编译代码。 /RTC on MSVC++ ,默认情况下在Debug配置中启用,它在函数序言中注入对_chkstk()的调用。GCC/g++具有 something very similar .

    它探测函数序言中分配的页面,每隔4096字节读取一次。这可以确保您在出错时始终点击保护页面,从而触发此站点的名称并帮助您修复错误。

    如果没有该检查,从技术上讲,您可以寻址根本不属于堆栈的页面。虽然它很可能触发处理器的#GP陷阱,但这并不能保证,因为页面可能已被另一个无关的分配映射。你一定很不幸,这已经完成了。基本的UB,诊断起来绝对可怕,因为你从未怀疑过堆栈,/RTC非常有价值。

        2
  •  1
  •   jwdonahue    6 年前

    当访问地址超出保护页时,程序将崩溃,但默认情况下,每当本地分配超过4K时,编译器将调用__chkstk()函数。

    这里有一篇文章解释了堆栈保护页在windows中的工作原理: kb100775