Home [C# 筆記] 内存垃圾回收機制(一)
Post
Cancel

[C# 筆記] 内存垃圾回收機制(一)

垃圾回收

內存管理(Memory Management)

內存管理指的是用戶為變量在heap(堆積/堆)上分配內存後,誰來管理釋放的問題

內存釋放

  • 程式員手動管理(C,C++)
  • 語言運行時自動管理(C#, Java, Python, JS)

當我們new一個對象的時候,會在heap內存上畫出了這麼一塊內存空間,然後在這裡面放上去當前這個class所需要的成員變量,然後將這塊內存的地址,給到了stack(堆疊/棧)內存上的一個「引用類型的變量」,那個變量就是我們在程式寫的那個對象/物件。

當一個方法壓入stack(堆疊/棧)內存的時候,這個方法裡面分配的簡單的的變量,例如一個小int,一個小float,會隨著方法的完成,在stack(堆疊/棧)內存隨著方法直接消失。

托管資源

  • 托管資源是.Net平台CLR提供的內存管理方法,由.Net負責內存生成及釋放
  • 托管資源
    • Stack(堆疊/棧)資源:根據函數運行自動分配釋放
    • 托管Heap(塊積/堆):用戶需要的時候new,不需要會自動釋放

非托管資源

CLR系統只能跟蹤其生存周其,而不能決定如何數放資源;如資料庫連接、文件句柄(file handle)及指針結果等

垃圾收集(Garbage Collection)

  • 垃圾收集即通過一定算法,得到內存中哪些對象需要被回收,並在GC階段將垃圾對象回收的過程
  • 從程序的根對象(Root)開始層層遍歷在Heap(堆積/堆)上分配的對象,不再被引用到的對象即判定垃圾;可被引用到的對象稱為Reachable Object

  • Root
    • 全局對象 (長期存在)(例如:單例模式)
    • 靜態變量 (長期存在)
    • Stack(堆疊/棧)上現存變量
    • CPU寄存器中變量

上兩個是:長期存在的,下兩個是:此時此刻我們是需要他們的

舉例

當執行完 showMe()方法後,在Stack內存的p1變量就會隨著方法消失

假設CLR現在要判斷一輪,剛好到達了他這個內存回收,垃圾回收時間點,它會看當前哪些內存該被回收,那很明顯了,p1變量消失了,那原來被p1所引這塊Heap內存(name,arr)是不是就變成需要被回收清理的內存呀

事還沒完呢,p1對象裡面還有name,arr這兩個變量所引用的這兩塊內存是誰呀?carma, 123,這兩塊是不是就變成無家可歸了,你會發現Stack上和Heap上都沒有任何的對象去引用這兩個塊內存了,所以也要消失了。

Mark-Compact標記壓縮算法

  • MC算法是C#採用的垃圾回收算單,具體分為兩個階段,即MarkCompact

  • 階段1:標記清除階段(Mark-Sweep) 假設所有對象都可回收,找出不能回收對象,打上標記

  • 階段2:壓縮階段(Compact) 移動不連續內存,從Heap基址開始排列

地址修複

  • Compact過程中,程動了Heap當中的對象,對象地發生變化,需要修複引用對象的Stack上變量、CPU寄存器變量及Heap上其他引用

總結

  1. C#採用CLR提供的托管內存辦法,利用GC來處理內存回收
  2. GCRoot對象開始遍歷,將對象分為:可達(Reachable)與不可達(Unreachable)
  3. GC採用Mark-Compact標記壓縮算法
  4. 內存Compact會觸發引用地址修復

https://www.bilibili.com/video/BV1HV411M7vN/

This post is licensed under CC BY 4.0 by the author.