C#学习:gc

gc

garbage collector

自动释放内存

为一个process分配自己的虚拟地址空间virtual address space

三种状态

  • free

  • reserved

  • committed

分配内存

开始进程后,保留连续的一块地址,叫做managed heap(不同于native heap

heap有一个pointer记录下一个object将被分配的地方,初始时位于基地址;当新对象生成后,pointer后移,直到空间完全分配。

释放内存

通过检查空间中不再需要的对象,检查方法,从roots出发,画gragh,不在graph中的object即unreachable

examining the application's roots. An application's roots include static fields, local variables on a thread's stack, CPU registers, GC handles, and the finalize queue. Each root either refers to an object on the managed heap or is set to null

释放过程,先释放unreachable的空间,当unreachable的对象个数达到一定程度,开始通过memory-copy方法将reachable的objects连续存储,重定向pointer

栈是用来静态分配内存的而堆是动态分配内存的,它们都是存在于计算机内存之中。

栈的分配是在程序编译的时候完成的,直接存储在内存中,接触内存很快。栈是后进先出的顺序,最后被申请的块最先被释放,这样就很容易跟踪到栈,释放栈的过程简单到仅仅是移动下指针就能完成。

堆的分配是在程序运行时完成的,分配速度较为缓慢,但是堆的可用空间非常的大。堆中的元素相互之间没有关联,各自都可以被任何时候随机访问。我们可以任何时候申请和释放一块内存,这样会使得我们很难随时随地追踪到堆中某块位置被分配了还是被释放了。

当你知道在编译前需要分配多少数据时且数据量不是很大时可以使用栈。如果不知道在运行时需要多少数据那么就该使用堆。

在多线程的程序里,每个线程都有其自己独立的栈,它们都共享一个堆。栈是面向线程的而堆是面向进程的。

回收

将对象分为三代,0,1,2逐个进化,高级代表生存时间长,更晚去访问获取空间

进化率动态调整

The garbage collector uses the following information to determine whether objects are live:

  • Stack roots. Stack variables provided by the just-in-time (JIT) compiler and stack walker. JIT optimizations can lengthen or shorten regions of code within which stack variables are reported to the garbage collector.

  • Garbage collection handles. Handles that point to managed objects and that can be allocated by user code or by the common language runtime.

  • Static data. Static objects in application domains that could be referencing other objects. Each application domain keeps track of its static objects.

不可管理资源

 unmanaged resources require explicit cleanup. The most common type of unmanaged resource is an object that wraps an operating system resource, such as a file handle, window handle, or network connection.

回收不可管理资源

当对象属于上述提及的种类时,需要自主管理内存。

而根据实现 Dispose 方法 | Microsoft Docs,当class的field或property中有类型实现了IDisposable

参考文章