原文
典型的c程式記憶體由以下幾個部分構成:
1. **段(text segment )
2. 資料段(initialized data segment)
3. bss段(uninitialized data segment)
4. 棧(stack)
5. 堆(heap)
1.**段
通常被用來儲存程式的可執行**,這部分區域大小在程式執行前就已經確定。
作業系統在裝載乙個程式時,**段通常位於最底部即最低位址的部分,堆和棧在記憶體空間高處,從而避免堆疊溢位時覆蓋**段。
通常**段是可共享的,所以對頻繁執行的程式,在記憶體中只需要有乙份**段的拷貝,例如文字編輯器,c compiler,shells等。**段經常是唯讀的,以此來避免程式無意間修改了自己的指令。
2. 資料段
已初始化的資料段,通常也被簡單叫做資料段。資料段是包含了程式已初始化的全域性變數和靜態變數的一段記憶體空間。資料段不是唯讀的,因此變數的值可以在執行時被改變。
資料段又可以細分為唯讀區和讀寫區。
全域性空間上的char s = 「hello world」和 int debug = 1 會儲存在讀寫區域。而像char* string = 「hello world"中的字串字面量「hello world"則被儲存在唯讀空間中,而字串指標string位於讀寫空間。
3. bss段
uninitialized data segment通常被稱為bss段(block started by symbol的簡稱,這是一條古老的彙編指令,用於定義符號並且為該符號預留給定數量的未初始化空間)。在程式執行之前,bss段中的資料被核心**初始化為0。
bss段位於資料段之後,包含了所有的未在**中顯式初始化的全域性和靜態變數。
4.棧通常棧毗鄰堆並且向著相反方向增長。當棧指標遇上堆時,空間耗盡。(在當今大位址空間和虛擬記憶體技術下,棧可以在任何地方,但是依然和堆向相反方向增長。)
棧是乙個lifo(last in first out先進後出)的結構。在標準的x86構架下它向0位址增長,而在另一些構架下它向著相反方向增長。乙個「棧指標」暫存器被用於定位棧頂,每次有值入棧時調整棧指標的位置。一次函式呼叫過程中入棧的資料的集合被稱為乙個「棧幀(stack frame)」,乙個棧幀最起碼要包含返回位址。
棧是區域性變數(automatic variables)儲存的地方,每次函式呼叫的資訊都存放在棧上。每一次的函式呼叫時,函式返回之後的位址以及呼叫者的資訊都被儲存在棧上。最近呼叫的函式會在棧上為它的自動變數和臨時變數分配空間。這也是c函式遞迴的工作方式,每一次遞迴都會有新的棧幀被使用,所以乙個函式例項中的資料集合不會受到另乙個函式例項的影響。
5.堆堆通常用於動態分配記憶體空間。
堆空間從bss段結束的地方開始,向高位址增長。在c中,堆空間用 malloc, realloc, 和free來管理,可以通過
brk、sbrk等系統呼叫來跳轉堆的大小。同乙個程序中所有的庫和動態載入模組都共享一塊堆空間。
C的記憶體布局
重點關注以下內容 c語言程式在記憶體中各個段的組成 c語言程式連線過程中的特性和常見錯誤 c語言程式的執行方式 一 c語言程式的儲存區域 由c語言 文字檔案 形成可執行程式 二進位制檔案 需要經過編譯 彙編 連線三個階段。編譯過程把c語言文字檔案生成匯程式設計序,彙編過程把匯程式設計序形成二進位制機...
C程式在記憶體中的布局
程式在記憶體中的分布 程式執行後在記憶體中分為4部分 區,資料區,堆區和棧區 源 已初始化的變數 未初始化的變數 堆空間 棧空間 命令列引數和環境變數 記憶體空間主要是堆疊 堆從低位址向高位址增長 棧從高位址向低位址增長。棧空間是靜態的儲存空間 函式的引數,函式的區域性變數儲存在棧區,函式呼叫時,需...
C 中物件的記憶體布局(三)
給出這樣的重複繼承 一 直接繼承,沒有虛函式存在時,書寫如下 class ca class cb public ca class cc public ca class cd public cb,public cc 檢視記憶體布局如下 由於b和c都繼承了a,所以在d中重複出現了a中的成員變數,所以當試...