欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

.NET中堆棧和堆的特點與差異介紹

 更新時間:2022年03月22日 08:34:51   作者:.NET開發(fā)菜鳥  
這篇文章介紹了.NET中堆棧和堆的特點與差異,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧

一、前言

.NET提供了垃圾回收機制,使程序員從內(nèi)存管理中被解放出來。但這并不代表程序員就無須了解分配的對象是如何被回收的。更重要的是,一些非托管的資源仍然需要程序員小心地分配與回收。

理解堆和堆棧是理解內(nèi)存管理的基礎(chǔ)。每一個.NET程序都最終會運行在一個操作系統(tǒng)進程中,假設(shè)這個操作系統(tǒng)是傳統(tǒng)的32位的,那每個.NET程序都可以擁有一個4GB的虛擬內(nèi)存。.NET會在這個4GB的內(nèi)存塊中開辟出三塊內(nèi)存分別作為堆棧、受托管的堆和非托管的堆。

二、.NET中的堆棧

.NET中的堆棧用來存儲值類型的對象和引用類型對象的引用,堆棧的分配是連續(xù)的,在.NET程序中,始終存儲了一個特殊的指針指向堆棧的尾部,這樣一個堆棧內(nèi)存的分配就直接從這個指針指向的內(nèi)存位置開始向下分配。下圖展示了.NET的堆棧分配方式。

如上圖所示,堆棧上的地址從高位開始往低位分配內(nèi)存,.NET只需要保存一個堆棧指針指向下一個未分配內(nèi)存的內(nèi)存地址。對于所有需要分配的對象,依次分配到堆棧中,其釋放也嚴格按照棧的邏輯,依次進行退棧。這里提到的“依次”,是指按照變量的作用域進行的??紤]下面的代碼:

ClassA a = new ClassA();
a.intA = 1;
a.intB = 2;

這里假設(shè)ClassA是一個引用類型,則堆棧中依次需要分配的是a的引用、a.intA和a.intB。當a的作用域結(jié)束后,這三個變量則從堆棧中依次退出:a.intB、a.intA,然后才是a。

三、.NET中的托管堆

接下來我們看一下托管的堆。.NET中的引用類型對象是分配在托管堆上的。通常我們稱.NET中的堆,指的就是托管的堆。和堆棧一樣,托管的堆也是進程內(nèi)存空間中的一塊區(qū)域。但托管堆中的內(nèi)存的分配卻和堆棧有很大的區(qū)別。受益于.NET的內(nèi)存管理機制,托管堆的分配也是連續(xù)的,但是堆中存在著暫時不能被分配卻已經(jīng)無用的對象內(nèi)存塊。當一個引用類型對象被初始化時,就會通過指向堆上可用空間的指針分配一塊連續(xù)的內(nèi)存,然后使堆棧上的引用指向堆上的這塊內(nèi)存塊。下圖展示了堆的分配方式。

如上圖所示,程序通過分配在堆棧中的引用來找到分配在托管堆的對象實例。當堆棧區(qū)域中的引用退出作用域時,就僅僅斷開引用和實際對象的聯(lián)系。而當托管堆中的內(nèi)存不夠時,.NET開始執(zhí)行垃圾回收。垃圾回收是一個非常復(fù)雜的過程,它不僅涉及托管堆中對象的釋放,而且需要移動合并托管堆中的內(nèi)存塊。當垃圾回收后,堆內(nèi)不被使用的對象才會被部分釋放,而在這之前,它們在堆內(nèi)是暫時不可用的。

四、.NET中的非托管堆

.NET的程序還包含了非托管的堆,所有需要分配堆內(nèi)存的非托管資源將會被分配到非托管堆上。非托管的堆需要程序員用指針手動地分配并且手動地釋放,.NET的垃圾回收和內(nèi)存管理制度不適用于非托管的堆。

五、堆棧、托管堆和非托管堆的比較

堆棧、托管堆和非托管堆的分配各有特點。堆棧的內(nèi)存是連續(xù)分配的,按照作用域依次分配和釋放。堆棧的機制非常簡單,.NET依靠一個堆棧指針就可以進行內(nèi)存操作,分配一個對象和釋放一個對象的大部分操作就是自增或者自減堆棧指針。.NET中的值類型對象和引用類型對象的引用是分配在堆棧內(nèi)的。

托管堆的內(nèi)存分配雖然也是連續(xù)的,但它卻比堆棧復(fù)雜得多。一塊堆內(nèi)存的分配需要涉及很多.NET內(nèi)存管理機制的內(nèi)部操作,另外當堆內(nèi)存不夠時,垃圾回收的執(zhí)行代價也是非常大的。相對于堆棧來說,堆的分配效率低得多。.NET中的引用類型對象是分配在托管堆上的,這些對象通過分配在堆棧上的引用來進行訪問。

非托管堆和托管堆的區(qū)別在于非托管堆不受.NET的管理。非托管堆的內(nèi)存是由程序員手動分配和釋放的,垃圾回收機制不適用于非托管堆,內(nèi)存塊也不會被合并移動,所以非托管堆的內(nèi)存分配按塊的,不連續(xù)的。

六、總結(jié)

.NET程序在進程內(nèi)存中分配出堆棧、托管堆和非托管堆。所有的值類型對象和引用類型對象的引用都分配在堆棧上,堆棧根據(jù)對象的生存周期來依次分配和釋放,堆棧根據(jù)一個指向棧尾的指針來分配內(nèi)存,效率很高。

.NET所有的引用類型對象分配在托管堆上,托管堆連續(xù)分配內(nèi)存,并且受.NET的垃圾收集機制管理,受托管堆的內(nèi)存分配和釋放涉及復(fù)雜的內(nèi)存管理,效率相對于堆棧來說低得多。

需要分配堆內(nèi)存的非托管類型將被分配在非托管堆上,非托管堆不受.NET垃圾收集機制管理,內(nèi)存塊完全由程序員手動申請和釋放。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

最新評論