回炉重造之重读Windows核心编程-016-线程的堆栈

按照默认设置系统为每个线程保留一个1MB的堆栈,修改的方式是链接程序的开关/STACK:reserve[.commit]。但是当用API创建线程时,可以重载原先提交的内存数量。如果这两个值是0,那么系统就使用开关指明的堆栈大小。

保留这个这个区域后,系统将物理存储器提交给该区域的顶部两个页面。在允许线程启动前,系统间现在的堆栈指针寄存器设置为指向堆栈区域的最高页面的结尾处(向高地址增长特性)。这个页面就是线程开始使用它的堆栈的位置。从顶部向下的第二个页面称为保护页面。堆栈空间随着需要增长。

每当线程要访问保护页面中的存储器,系统就会得到通知,然后系统将提交紧靠保护页面下面的另一个存储器,接下来系统删掉页面的保护标志,并将它赋予新提交的存储器页面。这样堆栈存储器只有在需要时才会增加。

当系统将物理存储器提交给0x08001000地址上面的页面时,它必须引发一个EXCEPTION_STACK_OVERFLOW异常处理。通过使用结构化异常处理,你的程序将得到关于这个异常处理条件的通知,并且实现适度恢复。

下面见代码清单Summation,展示如何对堆栈溢出进行适度恢复。

如果在出现这个异常后继续使用这个堆栈,系统就会引发一个访问违规异常条件。如果在线程访问该堆栈时引发了这个访问违规异常条件,线程会陷入很大的麻烦中。

16.1 Windows98下的线程堆栈

不重要

16.2 CC++运行期库的堆栈检查函数

CC++运行期库包含一个堆栈检查函数,在编译源代码时,编译器将在必要时自动生成对该函数的调用。这个函数的作用是确保页面被适当地提交给线程的堆栈。

MicrosoftVisualC++确是提供了一个编译器开关,使你能够控制一个页面大小的阈值,用来确定何时添加对StackCheck函数的自动调用。对于大多数应用程序和DLL来说,都不应该使用这个函数。

16.3 Summation示例应用程序

见代码清单。

猜你喜欢

转载自www.cnblogs.com/leoTsou/p/12446309.html