为什么声明极小.stack大小后大量入栈操作不会触发运行错误?
该现象的核心原因有三点:
1. .stack 伪指令的作用受限
.stack 是为16位DOS程序设计的汇编伪指令,在你使用的32位Windows平坦内存模型下,它的配置只会作为PE文件生成时的参考值,链接器和Windows加载器都会自动修正极不合理的栈大小配置,不会真的给你分配只有8字节的栈。
2. Windows栈采用动态提交的内存管理机制
Windows用户态线程栈的内存分为预留地址空间和已提交物理内存两层:
- 程序加载时,系统默认会为每个线程栈预留1MB的连续虚拟地址空间,哪怕你手动设置了极小的栈大小,链接器也会自动把栈大小对齐到内存页边界(通常单页大小为4KB),你设置的8字节会被自动对齐到4KB。
- 初始状态下系统只会提交栈顶的少数几页内存,当你执行压栈操作触发栈下方的内存页错误时,系统会自动校验访问地址是否在栈的预留地址范围内,只要不越界就会自动提交新的物理页供栈使用。你循环1024次
push ax总共才写入2KB数据,远小于4KB的最小提交页大小,自然不会报错。
3. 栈溢出的触发门槛远高于你的测试用例
只有当压栈操作越过了栈预留地址空间的底部,或者触发了栈下方的保护页(Guard Page)异常时,才会抛出栈溢出错误。你可以把循环次数调整到100万次以上,或者手动修改PE头的栈预留大小为极小值并关闭系统栈自动扩展,就能复现你预期的栈溢出错误。
内容的提问来源于stack exchange,提问作者Zackham
相关产品推荐
相关产品推荐

