C#之堆與棧

堆與棧

堆與棧都是記憶體空間的一部分,堆分為託管堆和非託管堆,託管堆由CLR管理,對非託管堆的管理則由開發者完成。

託管堆是執行程式時,CLR申請的一塊記憶體空間。

當建立新物件時,如果物件是引用型別或者包括引用型別的值型別,就會在GC堆上申請空閒的記憶體空間,CLR先計算需要的空間大小,如果堆上沒有剩餘空間了,就觸發一次垃圾回收,如果回收後仍舊沒有足夠的記憶體空間,就丟擲OutOfMemory異常。

為了合理利用空間,GC堆記憶體分配是連續的,垃圾回收結束,部分空間被釋放,會有記憶體碎片,此時進行壓縮,將記憶體重新變為連續狀態。

非託管資源佔用另一部分的記憶體,叫做本地堆或者非託管堆。CLR不負責這一塊的垃圾回收,常見的非託管資源有檔案流、資料庫連線、印表機資源等。

是一個先進後出的棧資料結構,所以一直是連續的。棧中的物件離開了定義域就會自動銷燬,所以棧一般空間是夠用的。爆棧也有例子,比如一個沒有出口的遞迴,此時所有的變數都還在它們的定義域中。

對於引用型別,也會使用棧,但棧只是儲存一個地址,即引用,就是它在堆上的記憶體地址,透過訪問棧上的地址就可以間接訪問到堆上的引用型別物件以及他們的值。

由於棧只能從頂部放入或者拿走資料,所以記憶體總是連續的,不需要進行GC。