栈(stack)为线程所有,是线程的一种特殊的内存结构。
系统为每一个线程分配一个stack, windows默认的stack大小为1M ,但是连接时指定 “/stack" 的开关可以调整stack的大小,格式: /stack: reserve[,commit]
stack具有“先进后出”的特点,局部变量的分配,函数传递的参数,push指令等都是在线程中的stack 中操作的。
线程执行时,esp总是指向栈顶(高地址端),随着入栈的深入,esp 越来越小,向栈底推进(低地址端)。系统如何防止stack溢出的呢??
假设 。0030000H~00130000H 为stack区域,那么该区域有三个块:
1: 00030000H~00092000H 为保留态(块1),大小 401408B
2: 00092000H~00093000H 为带有RAGE_GRARD 保护属性的 4kb 私有块(块2)
3: 00093000H~00130000H 为使用态(块3)
当线程执行时,首先使用stack中的块3,当块3 用完后,将访问块2。由于块2 有RAGE_GUARD保护属性,这时发生异常,系统接过控制权,它将重新分配块2和块1,提交部分的内存供进程使用。
这种异常将发生多次,以保证进程需要的栈空间,一直到靠近栈底部的倒数第二个页面被提交,但是不管怎么样,栈底部的最后一个页面,总是处于保留态,进程访问保留态的 页面时,将会违规,系统将“杀死”进程。保留块其实就象一堵墙,堵着你,不让你溢出。。
通俗的讲:stack就象吃甘蔗,“吃一截才去一截”。。。
这是 windows 2000/xp stack的特点,好处是物理存储器 提交总是 “物尽其用”,避免浪费。
heap : heap为进程所有,heap的默认大小也为1M,也可以再连接时调整大小。在一个进程中可以分配多个heap
heap 分为可生长heap和 不可生长heap。 当建议不可生长heap时,最大可分配的大小为7FFF8H。