DELPHI的原子世界(5)

2008-04-09 04:30:16来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折



第二节 进程空间
在我们用DELPHI编写WIN32的应用程序时,很少去关心进程在运行时的内部世界。因为WIN32为我们的进程提供了4G的连续虚拟进程空间,可能目前世界上最庞大的应用程序也只用到了其中的部分空间。似乎进程空间是无限的,但4G的进程空间是虚拟的,而你机器的实际内存可能与此相差甚远。虽然,进程拥有如此广阔的空间,但有些复杂算法的程序还是会因为堆栈溢出而无法运行,特别是含有大量递归算法的程序。
因此,深入地认识和了解这4G的进程空间的结构,以及它与物理内存的关系等等,将有助于我们更清楚地认识WIN32的时空世界,从而可在实际的开发工作中运用正确的世界观和方法论解决各种难题。
下面,我们将通过简单的实验,来了解WIN32的进程空间的内部世界。这可能需要一些对CUP寄存器和汇编语言的知识,但我尽量用简单的语言来说明。
当启动DELPHI时,将自动产生一个Project1的项目,我们就拿它开刀。在Project1.dpr原程序的任意位置设一断点,比如,就在begin一句处设一断点。然后运行程序,当程序运行到断点时会自动停下来。这时,我们就可以打开调试工具中的CPU窗口来观察进程空间的内部结构了。
当前的指令指针寄存器EIP是停在$0043E4B8,从程序指令所在地址的最高两位16进制数都是零,可以看出当前的程序处在4G进程空间相当底端的地址位置,其占据$00000000到$FFFFFFFF的相当少的地址空间。
在CPU窗口中的指令框中,你可以向上查看进程空间中的内容。当查看小于$00400000的空间内容时,你会发现小于$00400000的内容出现一串串的问号“????”,那是因为该地址空间还未映射到实际物理空间的缘故。如果在这时,你查看一下全局变量HInstance的16进制值就会发现它也是$00400000。虽然HInstance反映的是进程实例的句柄,其实,它就是程序被加载到内存中的起始地址值,在16位Windows中也是如此。因此,我们可以认为进程的程序是从$00400000开始加载的,也就是从4G虚拟空间中的4M以后的空间开始是程序加载的空间。
从$00400000往后,到$0044D000之前,主要是程序代码和全局数据的地址空间。在CPU窗口中的堆栈框中,可以查看到当前堆栈的地址。同样,你会发现当前堆栈的地址空间是从$0067B000到$00680000的,长度为$5000。其实,进程最小的堆栈空间大小就是$5000,它是根据编译DELPHI程序时在Project\Options中Linker页中设置的Min stack size值,加上$1000而得到的。堆栈是由高端地址向底端增长的,当程序运行的堆栈不够时,系统将自动向地端地址方向增加堆栈空间的大小,这一过程将把更多的实际内存映射到进程空间。可在编译DELPHI程序时,通过设置Project\Options中Linker页中Max stack size的值,控制可增加的最大堆栈空间。特别是在含有深层次的子程序调用关系或运用递归算法的程序中,一定要合理地设置Max stack size的值。因为,调用子程序是需要耗用堆栈空间,而堆栈耗尽之后,系统就会抛出“Stack overflow”的错误。
似乎,从堆栈空间之后的进程空间就应该是自由的空间了吧。其实不然,WIN32的有关资料说,$80000000之后的2G空间是系统使用的空间。看来,进程能够真正拥有的只有2G空间。其实,进程能真正拥有的空间连2G都不够,因为从$00000000到$00400000的这4M空间也是禁区。
但不管怎样,我们的进程可以使用的地址还是非常广阔的。特别是堆栈空间之后到$80000000之间,是进程空间的主战场。进程从系统分配的内存空间将被映射到这块空间,进程加载的动态连接库将被映射到这块空间,新建线程的线程堆栈空间也将映射到这块空间,几乎所有涉及分配内存的操作都将映射到这块空间。请注意,这里所说的映射,意味着实际内存与这块虚拟空间的对应,没有映射为实际内存的进程空间是无法使用的,就象调试时CPU窗口指令框中的那一串串的“????”。

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:在DELPHI 文 本 和 图 形 的 打 印

下一篇:在Delphi窗口中创建IE风格的菜单