【c語言】內存分區(內存佈局)

動態存儲和靜態存儲

動態儲存

  動態儲存是指在程序運行期間根據需要進行動態的分配

  函數形參,自動變量(沒有用static聲明的變量),函數調用時的現場保護和返回地址,對以上這些數據,在函數調用開始時分配動態存儲空間,函數結束時釋放這些空間,這種分配和釋放,是動態的,如果在一個程序中兩次調用同一個函數,則分配的局部變量的儲存空間可能是不相同的

靜態儲存

  靜態儲存是指在程序運行期間由系統分配固定的存儲空間

  全局變量和靜態變量(用static聲明的變量)全部存放在靜態存儲區中,在程序開始執行時,給變量分配存儲區,程序執行完畢才釋放

內存佈局

一個可執行程序沒有加載到內存前(運行前),可執行程序內部已經分好3段信息,分別爲代碼區(text)、初始化數據區(data)和未初始化數據區(bss)
在這裏插入圖片描述

通過命令:size 可執行程序名 即可查看

初始化數據區(data)和未初始化數據區(bss)有時並稱爲靜態區或全局區

  1. 代碼區(text)
      代碼區用於存放程序指令,主要是二進制代碼
  2. 靜態區或全局區(初始化數據區(data)和未初始化數據區(bss))
      靜態區或全局區中存放未初始化的數據、已經初始化了的數據、字符串常量(只有分配空間的數據纔可以使用,沒有分配空間的數據無法使用)

  初始化的數據
    1.初始化的全局變量
    2.初始化的靜態全局變量
    3.初始化的靜態局部變量
  未初始化的數據
    1.未初始化的靜態局部變量,該變量系統默認值爲0
    2.未初始化的全局變量,該變量系統默認值爲0
    3.未初始化的靜態全局變量,該變量系統默認值爲0
  字符串常量
    C語言對字符串是按字符數組來處理的,在內存中開闢了一個字符數組,用來存放該字符串常量,但是這個字符數中是沒有名字的,只能通過指針變量來引用

  1. 棧區(stack)當程序執行過程中,由程序自動開闢的額外空間,由編譯器自動分配釋放 ,存放函數的參數值,局部變量的值等。其操作方式類似於數據結構中的棧。
      局部變量、數組、結構體、指針變量、枚舉、函數形參均在棧中存儲

  申請

    只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,否則將報異常提示棧溢出。

    在Windows下,棧是向低地址擴展的數據結構即地址分配由高向低,是一塊連續的內存的區域。

    棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將提示overflow,能從棧獲得的空間較小。

  內容

  在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變量。注意靜態變量是不入棧的。

  當本次函數調用結束後,局部變量先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。

  1. 堆區(heap)一般由程序員分配釋放, 若程序員不釋放,程序結束時可能由OS(操作系統)回收 。注意它與數據結構中的堆是兩回事,分配方式倒是類似於鏈表
    申請

  首先應該知道操作系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時,會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序

  另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete(c++)/free©語句才能正確的釋放本內存空間。

  另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鏈表中。

  堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

  內容

  一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容有程序員安排。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章