C#高级编程9 第14章 内存管理和指针

时间:2023-03-09 07:43:25
C#高级编程9 第14章 内存管理和指针

C#高级编程9 内存管理和指针


后台内存管理

1) 值数据类型

在处理器的虚拟内存中有一个区域,称为栈,栈存储变量的浅副本数据,通过进入变量的作用域划分区域,通过离开变量的作用域释放.

栈的指针指向栈保留的内存块的末尾,栈是向下填充的,比如说内存是4g,,那么就从4g开始直至占用0g,每一个区域的划分都由下一个空闲存储单元。

2) 引用数据类型

变量的生存期是互相嵌套的,一般情况下变量的生存期在一个方法中定义会在一个方法外结束,不过有时候需要在方法外数据仍是可用的,这时候需要用到引用类型。

引用类型通过分配堆上的内存区域存储引用类型对象,把引用地址给栈,当引用类型脱离作用域时,栈中的引用地址被删除,但是堆上存储的对象还存在,直到程序终止或垃圾回收器删除,并且该数据没有任何引用时才会删除.

3) 垃圾回收

托管堆的分配内存的方式和栈分配内存的方式一样,使用下一个空闲存储单元的堆指针.

在垃圾回收器运行时,它会删除没有引用的所有对象,删除后把对象分散开来,与已释放的内存混合。

当垃圾回收器释放对象后,它会将其他对象移动到堆的端部,重新形成一个内存块。移动对象时,对象的引用都需要新的地址更新.它会处理更新问题.

4) 释放非托管资源

比如说网络连接、数据库连接、文件句柄这些资源就属于非托管资源。

4.1) 析构函数

含有析构函数的对象影响了对象在内存中删除的时间,没有析构函数的对象在垃圾回收器第一次处理中从内存中删除,有析构函数的对象,第2次处理中才能从内存中删除对象,运行库使用另一个线程执行Finalize()方法。频繁使用析构函数对性能的性能很显著。

4.2) IDisposable的接口

C#中使用IDisposable的接口替代了析构函数,实现IDisposable的接口的对象的引用超出作用域时,会自动调用Dispose()方法,释放对象所有的非托管资源.

using将语句变量的作用域限定于随后的语句块中,当变量超出作用域时,即时报异常也会调用Dispose()方法.

4.3) 实现析构函数和 IDisposable的接口

析构函数执行不确定,会给运行库增加不需要的开销.

IDisposable的接口,通过由用户来控制释放资源的时间,但一定要调用Dispose()方法.

5) 不安全代码