-线程栈
1.系统创建线程时,会为线程栈预订一块地址空间区域,并给区域调拨些物理存储器.
默认:预订1MB,调拨2页面。
应用指定:
/Freserve
/STACK:reserve[,commit]
API指定:
CreateThread/_beginthreadex。
2.举例:
页面大小设为4KB。
内存地址 | 页面状态 |
---|---|
0x080FF000 | 栈顶:已调拨页面 |
0x080FE000 | 带保护属性标志的已调拨的页面 |
0x080FD000 | 已预订的页面 |
… | … |
0x08001000 | 已预订的页面 |
0x08000000 | 栈底:已预订的页面 |
当线程试图访问防护页面中的内存时,系统会得到通知。
系统先给防护页面下的那页面调拨存储器,再去除防护页面的PAGE_GUARD标记,把该标记指定给新调拨页面。
新调拨页面为0x08001000时,不会给该页面指定该标记。这意味着栈的地址空间区域已放满了所有物理存储器。
永远不会给线程栈最底部页面调拨存储器。
给此页面调拨存储器时,还执行一额外操作:抛出EXCEPTION_STACK_OVERFLOW异常。通过结构化异常处理。系统会在发生这一情况时,通知程序,使其可得体地恢复。如试图访问0x08000000页面中内存,系统会抛出访问违规异常。
如在访问线程栈时,引发访问违规异常,系统会收回控制权,将其交给windows错误报告服务,后者,会弹出对话框,再终止进程。
应用可用SetThreadStackGuarante,来避免,借此抛出EXCEPTION_STACK_OVERFLOW。
-C/C++运行库的栈检查函数
确保已给线程栈调拨了物理存储器。