Chinaunix首页 | 论坛 | 博客
  • 博客访问: 301548
  • 博文数量: 108
  • 博客积分: 4260
  • 博客等级: 上校
  • 技术积分: 1145
  • 用 户 组: 普通用户
  • 注册时间: 2008-02-21 13:22
文章分类

全部博文(108)

文章存档

2011年(40)

2010年(22)

2009年(17)

2008年(29)

我的朋友

分类: WINDOWS

2010-12-02 16:20:29

从Stack说开去
 从我个人的经验看,谈到内存时说堆的文章最多,说stack的最少。我这里反其道而行的原因是stack其实要比堆更重要,可以有不使用堆的程序,但你不可能不使用stack,虽然由于对stack的管理是由编译器确定了的,进而他较少出错。
 
通过链接开关/STACK:reserve[,commit]可以指定进程主线程的stack大小,当你建立其他线程时如果不指定dwStackSize参数,则也将使用/STACK所指定的值。微软说,如果指定较大的commit值将有利于提升程序的速度,我没验证过,但理应如此。通常并不需要对STACK进行什么设定,缺省的情况下将保留1M空间,并提交两个页(8K for x86)。而1M空间对于大多数程序而言是足够的,但为防止stack overflow有三点需要指出一是当需要非常大的空间时最好用全局数组或用VirtualAlloc进行分配,二是引用传递或用指针传递尺寸较大的函数参数(这点恐怕地球人都知道),三是进行深度递归时一定要考虑会不会产生stack溢出,如果有可能,可以采用我在《递归与goto》一文中提到的办法来仿真递归,这时候可以使用堆或自由存储来代替stack。同时结构化异常被用来控制是否为stack提交新的页面。(这部分写的比较简略因为很多人都写过,推荐阅读Jeffery Ritcher《Windows核心编程》第16章)
 
下面我们来看一下stack的使用。
假设我们有这样一个简单之极的函数:
 
 
int __stdcall add_s(int x,int y)
{
int sum;
 
sum=x+y;
 
return sum;
}
 
这样在调用函数前,通常我们会看到这样的指令。
mov         eax,dword ptr [ebp-8]
push        eax
mov         ecx,dword ptr [ebp-4]
push        ecx
此时把函数参数压入堆栈,而stack指针ESP递减,stack空间减小。
 
在进入函数后,你将会看到如下指令:
push        ebp
mov         ebp,esp
sub         esp,44h
这三句建立stack框架,并减小esp为局部变量预留空间。建立stack框架后,[ebp+*]指向函数参数,[ebp-*]指向局部变量。
 
另外在很多情况下你会看到如下三条指令
push        ebx
push        esi
push        edi
这三句把三个通用寄存器压入堆栈,这样这三个寄存器就可以用来存放一些变量,进而提升运行速度。
很奇怪,我这个函数根本用不到这三个寄存器,可编译器也生成了上述三条指令。
 
对stack中内容的读取,是靠基址指针ebp进行的。所以对应于sum=x+y;一句你会看到
mov         eax,dword ptr [ebp+8]
add         eax,dword ptr [ebp+0Ch]
mov         dword ptr [ebp-4],eax
其中[ebp+8]是x,[ebp+0Ch]是y,记住压栈方向为从右向左,所以y要在x上边。
 
我们再看一下函数退出时的情况:
pop         edi
pop         esi
pop         ebx
mov         esp,ebp
pop         ebp
ret         8
此时恢复stack框架,使esp与刚进入这个函数时相同,ret 8使esp再加8,使esp与没调用这个函数的时候一致。如果使用__cdecl调用规则,则由调用方以类似add  esp,8进行清场工作,使stack的大小与未进行函数调用时一致。Stack的使用就这样完全被编译器实现了,只要不溢出就和我们无关,也许也算一种内存的智能管理。最后要补充的两点是:首先stack不像heap会自动扩充,如果你用光了储备,他会准时溢出。其次是不要以为你使用了缺省参数进行链接,你就有1M的stack,看看启动代码你就知道在你拥有stack之前,C Run –Time 
    Library以用去了一小部分stack的空间。
阅读(666) | 评论(0) | 转发(0) |
0

上一篇:windbg调试kvm windows虚机

下一篇:VS2010

给主人留下些什么吧!~~