线程的堆栈大小有上限值。线程创建时,系统会在进程地址空间的堆栈区,给线程预留这个大小的空间。
线程初始运行时,只提交了少量的页面(即大部分地址空间没有映射,作为保留页面)。
随着栈的深入,初始提交的页面不够用,就要扩充堆栈。
扩充堆栈只要将相邻页面,加入到进程的虚拟地址空间,并映射物理页面。
由于堆栈的访问具有空间局部性,所以系统根据缺页的地址和当前提交页面的距离来判断是否为堆栈扩展,如果是相邻页面,则视为堆栈的扩展,否则就视为段错误。
根据以上,
//由于堆栈的保留部分页面,是通过访问相邻的堆栈页面来扩展的。那么跳过相邻页面访问,在保留页面部分就会产生缺页,并且不会被当作栈的扩展处理,而是当作段错误处理。
因此,当访问到保留页面部分时,会因为段错误而退出。
//从堆栈的当前位置开始,逐个页面往下(低地址方向)访问,访问到保留页面时,系统会逐页提交它们,直到栈溢出(访问超出上限)。这样就遍历了堆栈的每个页面。
//测试程序只是从堆栈的当前位置开始,向低地址方向测试堆栈大小,而当前位置到栈底(最高地址处)的页面数,并没有测试到。
=======================================================
//加上Sleep后,可以通过任务管理器查看进程内存使用的变化,从而说明堆栈的扩展过程。