C# 之 垃圾回收机制

编程语言中的“垃圾”是指那些没有用的对象,如果不销毁便始终占用内存,造成内存泄漏,传统的C++语言因为没有自动垃圾回收的机制,所以需要程序员手动控制内存的分配和释放,一不小心就可能造成一些非常难以排查的问题,C++中实现了一种称为“引用计数”的方法(智能指针)来跟踪一个对象,被多少个其他对象引用了,如果引用计数为0则表示需要回收了,然而,这种引用计数的方式有一个缺点就是在处理循环引用的时候不是特别好

C++中采用了WeakPtr来解决循环引用的问题。

在C#里,因为其内部自动垃圾回收机制,极大限度的方便了程序的开发,让程序员更省心了,但是我们还是有必要去了解一下C#的垃圾回收机制是如何运作的,这样可以帮助我们对C#有更深的认识。

在介绍垃圾回收之前,我们需要先理解一个托管堆的概念。

堆、栈

可能之前你也听说过堆栈、堆、栈这些概念,他们是什么关系呢?

堆用来存放程序运行时的对象,而栈则用于保存现场(例如局部变量、函数参数、调用过程的地址等),二者都是一种满足LIFO的数据结构。

而堆栈其实就是栈

堆和栈的一些区别:

1.内存分配方式

堆:程序员控制分配和释放,如果未释放则将在程序结束后由系统释放

栈:操作系统控制

2.缓存级别

堆:二级缓存,回收受垃圾回收机制影响

栈:一级缓存,用完立马释放,所以栈更快一些,但缺乏灵活性

3.数据结构的区别

堆:可以看做是一棵树

栈:数据结构中的栈

托管堆

CLR要求所有对象都要从托管堆分配,进程初始化时,CLR划分出一个地址空间作为托管堆,创建的所有对象都分配在该托管堆内。CLR还要维护一个指针,NextObjPtr,指向下一个对象在堆中的分配位置。

如果这个地址空间被非垃圾对象填满,那么CLR会分配更多的区域,直到达到该进程所能分配空间的上限。

32位进程最多分配1.5GB,64位进程最多分配8TB

 在托管堆上添加一个对象是很快的,只需要在指针上加一个值即可。

为何需要垃圾回收?

答:虽然托管堆很牛逼,但毕竟内存是有限的。

垃圾回收算法

因为引用计数算法存在的问题(处理循环引用不太好),所以C#中采用了一种叫做引用跟踪的算法。

只关心引用类型的变量,把这些变量统称为,C#的垃圾回收过程大致可以这么描述:先把堆中的对象全部标记为要回收,然后检查所有活动根,如果这个根引用了某个堆里的对象,则把这个对象标记为不回收,然后进入压缩阶段,即把要回收的对象从堆里拿出去,然后调整其他幸存下来的对象,使他们占据一个连续的空间,然后所有的根指向的地址的值(减去其指向的对象在内存中移动的偏移量),调整NextObjPtr到最后一个幸存者之后。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值