三、栈内存
1、每个WINDOWS都有一个栈基址和栈限址,二者合在一起表示栈的有效内存范围。栈限址不是固定的,程序需要更多内存空间里,栈限址没有超过保留的栈内存范围,则可以要求更多的内存页
2、在栈限址外是栈的守护页,当访问到守护页时,会引发STATUS_GUARD_PAGE_VIOLATION异常,当异常发生后,操作系统捕捉后,提交下一页内存,然后将其做为新的守护页,这相当于分配了一个新的页给程序访问,就是栈动态增长。
具体机制是当访问了带PAGE_GUARD 属性的内存时,操作系统意识到当前栈内存已经用完,因为栈内存的下一页就是守护页,操作系统马上清除守护页的PAGE_GUARD 标志,将其用于补充当前的栈内存,同时申请一个新的内存页做为守护页,随着新守护页的不断申请,越来越多的老守护页加入当前栈空间,这就是动态增长
3、从MSDN中可以查到
A guard page provides a one-shot alarm for memory page access. This can be useful for an application that needs to monitor the growth of large dynamic data structures. For example, there are operating systems that use guard pages to implement automatic stack checking.
To create a guard page, set the PAGE_GUARD page protection modifier for the page. This value can be specified, along with other page protection modifiers, in the VirtualAlloc, VirtualAllocEx, VirtualProtect, and VirtualProtectEx functions. The PAGE_GUARD modifier can be used with any other page protection modifiers, except PAGE_NOACCESS.
If a program attempts to access an address within a guard page, the system raises a STATUS_GUARD_PAGE_VIOLATION (0x80000001) exception. The system also clears the PAGE_GUARD modifier, removing the memory page’s guard page status. The system will not stop the next attempt to access the memory page with a STATUS_GUARD_PAGE_VIOLATION exception.
If a guard page exception occurs during a system service, the service fails and typically returns some failure status indicator. Since the system also removes the relevant memory page’s guard page status, the next invocation of the same system service won’t fail due to a STATUS_GUARD_PAGE_VIOLATION exception (unless, of course, someone reestablishes the guard page).
The following short program illustrates the behavior of guard page protection.
保护页提供了一个内存页的访问警告,对应用程序监视,操作系统用它来实现栈的自动检查
在 VirtualAlloc, VirtualAllocEx, VirtualProtect, and VirtualProtectEx 函数中可以定义这个参数
目前我们使用VB.NET进行多线程编程,使用的是.NET的CLR托管线程,CLR使用了SetThreadStackGuarantee来以更大的增量来递增栈限址,这个API指定了守护区域大小,如果将大小设置为0,则返回当前的守护区域大小。
3、运用stacktrace类实现线程栈回溯跟踪
代码如下:
Imports System
Imports System.Threading
Imports System.Diagnostics.StackTrace
Module Module1
Sub Main()
Dim main_x As Integer
main_x = 5
Call sub1(main_x)
End Sub
Private Sub sub1(sub1_x As Integer)
Dim jg As Integer
jg = sub1_x * sub1_x