您的位置:首页 > 其它

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

2012-08-10 00:13 323 查看
首先,通过我们最熟悉的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的对象中回收,因为这些是最新的,所以最有可能会被回收,比如一些函数中的局部变量在退出函数时就没有引用了(可被回收)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: