淺談操作系統棧和堆(區別與聯系)


操作系統棧和堆

地址空間布局:
-c

棧:

        執行期間編譯器自動分配,編譯器用它實現函數調用,調用函數時,棧增長,函數返回時,棧收縮。局部變量、函數參數、返回數據、返回地址等放在棧中

棧的特點

  1. 內存分配取決於編譯器,用戶棧在程序運行期間可以動態的擴展和收縮。
  2. 和數據結構中的“棧”本質上是不一樣的,但是操作方式類似於棧。
  3. 數據從棧中的進出滿足“后進先出”的規律。
  4. 棧向低地址方向增長,esp(棧指針)指向棧頂元素。

堆:

        動態儲存器分配器維護着的一個進程的虛擬存儲器區域。一般由程序員分配釋放(堆在操作系統對進程初始化的時候分配),若程序員不釋放,程序結束時可能由OS回收,每個進程,內核都維護着一個變量brk指向堆頂。

堆的特點

  1. 內存分配取決於程序員,C/C++可以手動釋放該片內存。
  2. 和數據結構的”堆“完全兩回事,沒有半點關系,在這里堆的結構更像鏈表。
  3. 所有的對象,包括數組的對象都存在堆上。
  4. 堆內存被所有的線程共享。
  5. 引用類型總是放在堆中。
  6. 堆向高地址方向增長,內核都維護的變量brk指向堆頂。

注意:值類型和指針總是放在他們被聲明的地方(復雜)
當值類型的數據在方法體內被聲明時,它們都應該放在棧上。
如果一個只類型被聲明在方法體外且存在於一個引用類型中,那么它將會被堆里的引用類型所取代。

全局區/靜態區:

        全局變量、靜態變量、常量的存儲區域,程序終止時系統釋放。

文字常量區:

        存放常量字符串,程序結束后由系統釋放。

程序代碼區:

        存放函數體(類成員函數和全局函數)的二進制代碼。

實例

int a = 0;        //全局初始化區
char *p1;       //全局未初始化區
void main()
{
    int b;          //棧
    char s[] = "123";  //棧
    char *p2;       //棧
    char *p3 = "sdfghhj"; //其中,“sdfghhj\0”常量區,p3在棧區
    static int c = 0; //全局區
    p1 = (char*)malloc(10);   //10個字節區域在堆區
    strcpy(p1,"sdfghhj");    //"sdfghhj\0"在常量區,編譯器可能會優化p1和p3指向同一塊區域

}

棧和堆的區別:

  1. 棧內存存儲的的是局部變量,堆內存存儲的是實體。
  2. 棧內存的更新的速度會更快些(局部變量),堆內存的更新速度相對更慢。
  3. 棧內存的訪問直接從地址讀取數據到寄存器,然后放到目標地址,而堆內存的訪問更麻煩,先將分配的地址放到寄存器,在讀取地址的值,最后再放到目標文件中,開銷更大。
  4. 棧內存是連續的空間,堆內存一般情況不是連續的,頻繁地開辟空間,釋放空間容易產生內存碎片(外碎片)。

棧和堆的聯系:

        堆中對象是直接由棧中的句柄(引用)管理者,所以堆負責產生真實對象,棧負責管理對象。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM