一條進程的棧區、堆區、數據區和代碼區在內存中的映射

2020-12-23 電子產品世界

l棧區:主要用來存放局部變量,傳遞參數,存放函數的返回地址。.esp始終指向棧頂,棧中的數據越多, esp的值越小。

l堆區:用於存放動態分配的對象,當你使用malloc和new等進行分配時,所得到的空間就在堆中。動態分配得到的內存區域附帶有分配信息,所以你能夠free和delete它們。

本文引用地址:http://www.eepw.com.cn/article/201611/317090.htm

l數據區:全局,靜態和常量是分配在數據區中的,數據區包括bss(未初始化數據區)和初始化數據區。

注意:

1)堆向高內存地址生長;

2)棧向低內存地址生長;

3)堆和棧相向而生,堆和棧之間有個臨界點,稱為stkbrk。

1、一條進程在內存中的映射

假設現在有一個程序,它的函數調用順序如下:

main(...) ->; func_1(...) ->; func_2(...) ->; func_3(...),即:主函數main調用函數func_1;函數func_1調用函數func_2;函數func_2調用函數func_3。

當一個程序被作業系統調入內存運行,其對應的進程在內存中的映射如下圖所示:

注意:

l隨著函數調用層數的增加,函數棧幀是一塊塊地向內存低地址方向延伸的;

l隨著進程中函數調用層數的減少(即各函數調用的返回),棧幀會一塊塊地被遺棄而向內存的高址方向回縮;

l各函數的棧幀大小隨著函數的性質的不同而不等,由函數的局部變量的數目決定。

l未初始化數據區(BSS):用於存放程序的靜態變量,這部分內存都是被初始化為零的;而初始化數據區用於存放可執行文件裡的初始化數據。這兩個區統稱為數據區。

lText(代碼區):是個只讀區,存放了程序的代碼。任何嘗試對該區的寫操作會導致段違法出錯。代碼區是被多個運行該可執行文件的進程所共享的。

l進程對內存的動態申請是發生在Heap(堆)裡的。隨著系統動態分配給進程的內存數量的增加,Heap(堆)有可能向高址或低址延伸,這依賴於不同CPU的實現,但一般來說是向內存的高地址方向增長的。

l在未初始化數據區(BSS)或者Stack(棧區)的增長耗盡了系統分配給進程的自由內存的情況下,進程將會被阻塞,重新被作業系統用更大的內存模塊來調度運行。

l函數的棧幀:包含了函數的參數(至於被調用函數的參數是放在調用函數的棧幀還是被調用函數棧幀,則依賴於不同系統的實現)。函數的棧幀中的局部變量以及恢復該函數的主調函數的棧幀(即前一個棧幀)所需要的數據,包含了主調函數的下一條執行指令的地址。

2、函數的棧幀

函數調用時所建立的棧幀包含下面的信息:

1)函數的返回地址。返回地址是存放在主調函數的棧幀還是被調用函數的棧幀裡,取決於不同系統的實現;

2)主調函數的棧幀信息,即棧頂和棧底;

3)為函數的局部變量分配的棧空間;

4)為被調用函數的參數分配的空間取決於不同系統的實現。

注意:

lBSS區(未初始化數據段):並不給該段的數據分配空間,僅僅是記錄了數據所需空間的大小。

lDATA(初始化的數據段):為數據分配空間,數據保存在目標文件中。


相關焦點

  • 走進C語言:堆、棧與堆區、棧區,你知道有什麼區別嗎?
    5個區:棧區、堆區、靜態區、常量區、代碼區。每個區存儲的內容如下: 1、棧區:存放函數的參數值、局部變量等,由編譯器自動分配和釋放,通常在函數執行完後就釋放了,其操作方式類似於數據結構中的棧。棧內存分配運算內置於CPU的指令集,效率很高,但是分配的內存量有限,比如iOS中棧區的大小是2M。
  • 棧:如何實現有效括號的判斷?
    很著名的就是斐波那契數列[3]F(0) =0,F(1) =1,F(n) = F(n-1)+F(n-2)(n≥2,n∈N*)計算F(n)時需要先計算F(n-1)和F(n-2)計算F(n-1)時需要先計算F(n-2)和F(n-3)計算F(n-2)時需要先計算F(n-2)和F(n-3)···最後的效果是,會有很多中間值壓入棧中,這也是為什麼,當n很大的時候
  • 內存分配的三種情況解析:靜態、棧區、堆區
    打開APP 內存分配的三種情況解析:靜態、棧區、堆區 佚名 發表於 2017-12-15 11:26:02 內存分配分為三種:靜態、棧區、堆區分別解釋 (1)靜態存儲區:主要存放static靜態變量、全局變量、常量。
  • [C++學習筆記]內存模型常見問題梳理
    C++語言規定,C++的內存分為4個區域,分別是代碼區,全局區,棧區,堆區。代碼區也就是可執行二進位文件存放的位置,不可修改。全局區或者說靜態區,存放全局變量,常量,和靜態變量。全局變量,就是在一個源碼文件中,函數外,直接聲明的不加任何修飾的變量和常量。靜態變量就是以static修飾的,函數內部變量和函數外靜態變量,靜態函數也即static修飾的函數。
  • WinCE內存管理報告
    當我們按下後面的Reset按鈕後,Windows CE內核在RAM中尋找最近一次創建的對象存儲,如果找到的話,就是用這個對象存儲重新啟動。l RAM的另一個區域是程序區。這個區域就像PC機的RAM一樣。它存放所運行程序的堆和棧的空間。對象存儲和程序區的界限是可移動的。在低內存的情況下,系統會請求用戶把部分可用的存儲對象空間提供給運行程序使用,以滿足程序運行的RAM需要。
  • 程式設計師每日一題-jvm裡方法和方法區、棧區的二三事
    JAVA虛擬機運行時數據區的邏輯圖好,對照上圖,逐項解釋A:堆區是JVM 所管理的內存中最大的一塊。線程共享,主要是存放對象實例和數組。堆區是jvm裡面最需要深入研究的一塊區域,這裡面涉及內存分配,區域劃分,對象信息,垃圾回收。可以說如果java程式設計師對堆區不熟悉,那麼一定寫不出好的代碼。本文暫時不深入討論,後續會開專題深入講解。B:棧區,也叫虛擬機棧,顧名思義,它是一個棧,先進後出。它是線程創建時跟著創建,生命周期和線程一致,是線程私有的。
  • 堆棧在C語言中的定義(單片機的中堆棧相當於棧)
    內存分配中的棧和堆 然而我要說的重點並不在這,我要說的堆和棧並不是數據結構的堆和棧,之所以要說數據結構的堆和棧是為了和後面我要說的堆區和棧區區別開來,請大家一定要注意。 下面就說說C語言程序內存分配中的堆和棧,這裡有必要把內存分配也提一下,大家不要嫌我囉嗦,一般情況下程序存放在Rom或Flash中,運行時需要拷到內存中執行,內存會分別存儲不同的信息,如下圖所示:
  • 看完這篇,輕鬆區別堆與棧!
    註:首先堆和棧可以分為兩種,一種是數據結構,另一種是和內存的分配有關,這兩種雖然都有棧和堆,但是兩者關係並不大, 1、棧、堆是數據結構裡面的叫法,注意:有時候有人喜歡這樣說 「堆棧」 其實說的就是棧而不是堆。 2、堆區、棧區則是內存模型的叫法。
  • JVM筆記四-棧區
    JVM學習筆記之棧區本文主要內容:棧是什麼?棧幀又是什麼?在JVM中,main方法調用say方法後,是怎麼運行的?本文將詳細講解棧。希望大家學了之後,對棧有更深的了解。心法:在JVM中,棧管運行,堆管存儲。
  • 獨家|Linux進程內存用量分析之堆內存篇
    如果進程存在內存洩漏會在進程結束後,列印出所有洩漏的內存大小和申請這塊內存的調用棧,如下圖所示:                     AddressSanitizer檢測內存洩漏另一個工具Valgrind的優勢在於不需要重新編譯,只需要在運行時加上valgrind --leak-check=yes即可。
  • Java內存分配和String類型的深度解析
    2、java內存分區從上節知道,運行時數據區即是java內存,而且數據區要存儲的東西比較多,如果不對這塊內存區域進行劃分管理,會顯得比較雜亂無章。程序喜歡有規律的東西,最討厭雜亂無章的東西。在此方法執行期間,這個幀將用來保存參數、局部變量、中間計算過程和其他數據。從Java的這種分配機制來看,堆棧又可以這樣理解:棧(Stack)是作業系統在建立某個進程時或者線程(在支持多線程的作業系統中是線程)為這個線程建立的存儲區域,該區域具有先進後出的特性。其相關設置參數:本地方法棧(Native Stack):存儲本地方方法的調用狀態。
  • Java虛擬機系列一:一文搞懂 JVM 架構和運行時數據區
    如下圖所示,程序計數器、Java 虛擬機棧和本地方法棧是線程私有的,堆和方法區是線程共享的,其中方法區又包含了運行時常量池。下面就對這個部分做個詳細的介紹吧 (註:本部分引用內容來自《深入理解Java虛擬機》)。
  • 關於PHP語言在內存中的分配(堆和棧的區別)
    他們在運行的時候都要加載到內存中去用,那麼在內存裡面它們是怎麼表示的呢?初始化靜態常量段:通常是指用來存放程序中已初始化且不為0的全局變量如:靜態變量和常量。代碼段:通常是指用來存放程序執行代碼的一塊內存區域,比如函數和方法。
  • 乾貨——聊聊內存那些事(基於單片機系統)
    內存主要分為:代碼區、常量區、靜態區(全局區)、堆區、棧區這幾個區域。>l  棧區:存放函數內的局部變量,形參和函數返回值。棧區之中的數據的作用範圍過了之後,系統就會回收自動管理棧區的內存(分配內存 , 回收內存),不需要開發人員來手動管理。棧區就像是一家客棧,裡面有很多房間,客人來了之後自動分配房間,房間裡的客人可以變動,是一種動態的數據變動。 STM32F103C8T6中
  • JVM(堆、方法區、棧、這些基礎您知道了嗎)
    堆(Heap-線程共享)主要存儲: New對象、數組、包括JDK1.7從方法區移過來的字符串常量和靜態變量、還有 線程分配緩衝區(TLAB)當前主流的Java虛擬機都是按照可擴展來實現的(通過參數-Xmx和-Xms設定)、如果在Java堆中沒有內存完成實例分配,並Java虛擬機將會拋出OutOfMemoryError
  • 這一定是全網寫JVM最好的文章之一—JVM運行時數據區
    Java內存區域根據上圖可以知道,方法區和堆是一個顏色,虛擬機棧和本地方法棧和程序計數器是一個顏色 所以,方法區和堆是線程共享的,虛擬機棧和本地方法棧和程序計數器是線程私有的通過上圖,可知Java內存區域包括運行時數據區和執行引擎和本地庫接口和本地方法庫運行時數據區
  • JVM-概述和內存區域
    方法區和堆區是所有線程共享的內存區域;Java棧又叫做jvm虛擬機棧。執行引擎等同於翻譯class文件的語言翻譯器。方法區(永久代)在jdk8中又叫做元空間Metaspace運行時數據區概述堆內存:保存所有引用數據的真實信息;棧內存:基本類型、運算、指向堆內存的指針;方法區:所以定義的方法的信息都保存方法區中,屬於共享區
  • 深入分析Java虛擬機堆和棧及OutOfMemory異常產生原因
    Heap(堆)堆是Java虛擬機所管理內存中最大的一塊,在虛擬機啟動時創建,被所有線程共享。堆在虛擬機啟動時創建,用於存儲所有的對象實例和數組(在某些特殊情況下不是)。堆中的對象永遠不會顯式地釋放,必須由GC自動回收。
  • 談談java的棧和堆
    先用一張圖展示一下Java堆棧的概況堆方法區:class文件信息,運行時常量池,以及編譯器編譯後的代碼堆:存儲對象,對象包含類的信息,指向方法區>棧虛擬機棧:表示Java方法執行的內存模型,每調用一個方法就會為每個方法生成一個棧幀(Stack Frame),用來存儲局部變量表、操作數棧、動態連結、方法出口等信息。