<整理>:进程动态请求和释放内存(待)

首先,通过我们最熟悉的C语言来看下动态请求和释放内存的一些概念   程序(进程)只能访问属于自己的内存数据空间。这个数据空间可以是静态分配的(如定义变量),也可以是动态分配的(如用 malloc 函数等)。静态分配的空间由操作系统直接管理,负责分配和释放;动态分配的空间是人们向操作系统申请,经操作系统同意而划归给本进程使用的内存空间。只要进程没有向操作系统提出“释放”(free)这块空间的请求,操作系统就会保证这块内存空间是本进程专有的。

一个进程完全可以只申请内存空间(malloc),而不释放(free)空间。但是请想一下,如果进程不断地 malloc(比如在一个循环过程中),系统的内存资源很快就会用光

的。所以,用过的内存空间如果不再需要了,立即释放是一个好习惯。

       C语言中,动态分配的内存只能通过指针来访问。前面已经提到过,程序只能访问属于自己的内存数据空间。如果一个指针访问到了不属于自己的内存空间,程序会在输出

Segmentation fault 之后异常终止。根据这一点,我们可以判断内存空间在 free之后,系统到底是否真正地回收了这块空间:如果是真正地释放了,再次访问这块空间会产

Segmentation fault的错误,程序会异常终止;如果不是真正释放,而是到了程序结束时才真正释放,由于这块内存还属于程序专有,只要程序没有结束,应该就还能正常访

问这块内存,就象没有释放过一样,程序正常结束。

C  Code:

#include "stdio.h"
#include "conio.h"
#include"malloc.h"

main()
{
       /*动态申请内存*/
      int *p=(int *)malloc(sizeof(int));
      int *q=(int *)malloc(sizeof(int));

      int *m;

      *p=123;

      *m=123;

      q=p;

      printf("%d\n",*p);
      printf("%d\n",*q);
      printf("%d\n",*m);


      /*释放内存*/
      free(p);

      /*p,q都变成野指针,随机的指向内存*/
      printf("%d\n",*p);
      printf("%d\n",*q);
      printf("%d\n",*m);

    getch();
}

从上面可以看出,早期完全以手工方式使用App来完成这些工作,但是这很容易导致内存泄露,因为很容易被遗漏,后期又有了维护引用计数,但是呢.Net平台中,CLR为程序

员提供

了一种很好的内存管理机制,使得程序员在编写代码时不需要显式的去释放自己使用的内存资源。这种管理机制称

为GC(garbage collection)。GC的作用是很明显的,当系统内存资源匮乏时,它就会被激发,然后自动的去释放那些没有被使用的托管资源(也就是程序员没有显式释放的对象)。

但是呢,这里有个问题,既然有托管资源,那么一定存在非托管资源,那么概念又是什么呢?简单的说:托管资源一般是指被CLR控制的内存资源,这些资源的管理可以由

CLR来控制;而非托管资源是CLR不能控制或者管理的部分,这些资源有很多,比如文件流,数据库的连接,系统的窗口句柄,打印机资源等等;


正如上面说的,CLR的GC功能也只能释放托管资源,对于非托管资源例如窗口,文件和网络连接等,它都只能跟踪非托管资源的生存期,而不知道如何去释放它。这样就会出

现当资源用尽时就不能提供资源能够提供的服务,windows的运行速度就会变慢。这样的情况会出现在数据库的连接当中,当你没有显式的释放一个数据库资源时,如果还是不

断的申请数据库资源,那么到一定时候程序就会抛出一个异常。


所以,当我们在类中封装了对非托管资源的操作时,我们就需要显式,或者是隐式的释放这些资源。而上面提到的Finalize和Dispose方法分别就是隐式和显式操作中分别使用

到的方法。


Finalize一般情况下用于基类不带close方法或者不带Dispose显式方法的类,也就是说,在Finalize过程中我们需要隐式的去实现非托管资源的释放,然后系统会在Finalize过程

完成后,自己的去释放托管资源。


如果要实现Dispose方法,可以通过实现IDisposable接口,这样用户在使用这个类的同时就可以显示的执行Dispose方法,释放资源。


GC为了提高回收的效率使用了Generation的概念,原理是这样的,第一次回收之前创建的对象属于Generation 0,之后,每次回收时这个Generation的号码就会向后挪一,也就是说,第二次回收时原来的Generation 0变成了Generation 1,而在第一次回收后和第二次回收前创建的对象将属于Generation 0。GC会先试着在属于Generation 0的对象中回收,因为这些是最新的,所以最有可能会被回收,比如一些函数中的局部变量在退出函数时就没有引用了(可被回收)。















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验内容: 编写一个动态分区分配算法模拟程序,加深对动态分区存储管理方式及其实现过程的理解。 要求: 1.空闲分区通过空闲区链进行管理,在内存分配时,优先考虑低地址部分的空闲区。 2.分别采用首次适应算法、最佳适应算法和最坏适应算法模拟内存空间的动态分配与回收,每次分配和回收后显示出空闲区链的详细情况(说明:在申请不成功时,需要打印当前内存的占用情况信息)。 3.进程内存空间的申请释放可由用户自定义输入。 4.参考请求序列如下: (1) 初始状态下可用内存空间为640KB; (2) 进程1申请130KB; (3) 进程2申请60KB; (4) 进程3申请100KB; (5) 进程2释放60KB; (6) 进程4申请200KB; (7) 进程3释放100KB; (8) 进程1释放130KB; (9) 进程5申请140KB; (10) 进程6申请60KB; (11) 进程7申请50KB; (12) 进程6释放60KB。 测试用例格式如下: 输入: 动态分区分配算法选择 可用内存空间容量 序号/进程号/申请释放操作/申请释放的容量 其中: (1) 动态分区分配算法:1----首次适应,2----最佳适应,3----最坏适应 (2) 申请释放操作: 1----申请操作,2----释放操作 输出: 序号/内存空间状态1/内存空间状态2...... 内存空间状态表示分为两种情况: (1) 内存空间被占用: 内存空间起始地址-内存空间结束地址.1.占用的进程号 (2) 内存空间空闲 内存空间起始地址-内存空间结束地址.0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值