进程的内存管理

12 篇文章 0 订阅

一、在操作系统中,系统会给每个进程分配虚拟地址,虚拟地址的大小与处理器的位数有关,如32位处理器进程可分配4GB的虚拟内存供程序正常运行。
这4GB的虚拟内存,存储单元从地址0开始进行排序,此地址为虚拟地址。
此虚拟地址可分为:
1、栈区(stack):由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。线程也有自己维护的栈。
2、堆区(heap) :程序动态申请的空间,由程序释放或其他方式释放,若没有释放,可能导致内存泄露。    
3、全局区(静态区)(static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 
4、文字常量区:常量字符串就是放在这里的。 程序结束后由系统释放
5、程序代码区:存放函数体的二进制代码。


二、下面主要分析栈区和堆区的分配和释放方式:
1、栈区:栈区是从高地址往低地址分配的,初始的栈区栈指针指向栈的最高地址单元,而释放总是从低地址往高地址释放(先进后出)。栈区的分配与释放由编译器自动完成
如下:
{
   int a;
   //do something
  {
   double b ;
   //do something
   }
}
整形a将先入栈高地址空间,占4个字节,接着双精度浮点数b入栈,占8个字节。变量b的作用域比a先结束,于是b所占据的空间先被回收。
如下图所示,红色区域为已占用区,黄色区域为空闲区

带引用的情况:
{
    Customer  a;
   a = new Customer();
}
此种情况a将在栈区分得4个单元空间以存放Customer实例的地址。
Customer对象将存储在堆上。


2、堆区:

堆区与栈区的地址结构类似,不同点在于:

a、需要程序主动申请,释放根据不同的语言释放方式不同(c、c++、delphi等需要程序显示释放,.net有自动回收机制)

b、堆区是由低地址向高地址分配的。释放的顺序是不定的,基于堆上对象的生存周期。会产生内存碎片。



三、内存的释放
1、写delphi程序时我们通常强调内存哪里申请哪里释放,因为delphi的程序是程序代码负责释放内存,又称为纯手工释放方式。
     这种方式的有点是内存能够得到及时释放,而缺点是由于手工,我们可能常忘记写释放代码,导致内存泄露出现错误,而这种错误通常又很难跟踪定位泄露的地方。
在实际工作中已遇到过不少此类情况,排错的过程很是头痛,解决办法就是不要忘记释放对象。
2、在ms中COM采用的是对象维护引用技术。COM对象自己维护一个计数,记录自己被引用的次数,当这个计数变为0时,也就是不会再用时,COM自己释放掉内存。
3、.net的运行库采用的是垃圾回收器来回收的方式。垃圾回收器本身也是一个程序。程序动态请求的内存都分配到堆上,在.net中,CLR维护它自己的托管堆供.net程序使用。
      每隔一段时间.net就会检查托管堆,当检查到需要清理堆时,.net就调用垃圾回收器这个程序。垃圾回收器会扫描堆上的对象的引用,不再有引用的对象就被删除。
      垃圾回收器调用的时间是不确定的,除非代码中有调用垃圾回收器(System.GC.Collect())。关于.net非托管堆内存释放将在下一篇中讲解。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值