C和C 記憶體模型

2021-07-03 16:25:30 字數 2305 閱讀 4424

c分為四個區:堆,棧,靜態全域性變數區,常量區

c++分為四個區:堆,棧,靜態全域性變數去,常量區,自由儲存區。

根據c/c++物件生命週期不同,c/c++的記憶體模型有三種不同的記憶體區域,即自由儲存區,動態區、靜態區。

自由儲存區:區域性非靜態變數的儲存區域,即平常所說的棧

動態區: 用operator new ,malloc分配的記憶體,即平常所說的堆

靜態區:全域性變數 靜態變數 字串常量存在位置

而**雖然佔記憶體,但不屬於c/c++記憶體模型的一部分

在linux系統中,程式在記憶體中的分布如下所示:

低位址.text

.data

.bss

heap(堆) 

-->

unused  

stack

(棧)  

env高位址

其中 :

.text 部分是編譯後程式的主體,也就是程式的機器指令。

.data 和 .bss 儲存了程式的全域性變數,.data儲存有初始化的全域性變數,.bss儲存只有宣告沒有初始化的全域性變數。

heap(堆)中儲存程式中動態分配的記憶體,比如c的malloc申請的記憶體,或者c++中new申請的記憶體。堆向高位址方向增長。

stack(棧)用來進行函式呼叫,儲存函式引數,臨時變數,返回位址等。

是「block started by symbol」的縮寫,意為「以符號開始的塊」。

bss是unix鏈結器產生的未初始化資料段。其他的段分別是包含程式**的 「text」段和包含已初始化資料的「data」段。bss段的變數只有名稱和大小卻沒有值。此名後來被許多檔案格式使用,包括pe。「以符號開始的塊」 指的是編譯器處理未初始化資料的地方。bss節不包含任何資料,只是簡單的維護開始和結束的位址,以便記憶體區能在執行時被有效地清零。bss節在應用程式 的二進位制映象檔案中並不存在。

在採用段式記憶體管理的架構中(比如intel的80x86系統),bss段(block started by symbol segment)通常是指用來存放程式中未初始化的全域性變數的一塊記憶體區域,一般在初始化時bss 段部分將會清零。bss段屬於靜態記憶體分配,即程式一開始就將其清零了。

比如,在c語言之類的程式編譯完成之後,已初始化的全域性變數儲存在.data 段中,未初始化的全域性變數儲存在.bss 段中。

text和data段都在可執行檔案中(在嵌入式系統裡一般是固化在映象檔案中),由系 統從可執行檔案中載入;而bss段不在可執行檔案中,由系統初始化。

各個段的關係

圖3-1所示為可執行**儲存時結構和執行時結構的對照圖。乙個正在執行著的c編譯程式占用的記憶體分為**區、初始化資料區、未初始化資料區、堆區 和棧區5個部分。

(1)**區(text segment)。**區指令根據程式設計流程依次執行,對於順序指令,則只會執行一次(每個程序),如果反覆,則需要使用跳轉指令,如果進行遞迴,則需 要借助棧來實現。

**區的指令中包括操作碼和要操作的物件(或物件位址引用)。如果是立即數(即具體的數值,如5),將直接包含在**中;如果是區域性資料,將在棧區 分配空間,然後引用該資料位址;如果是bss區和資料區,在**中同樣將引用該資料位址。

(2)全域性初始化資料區/靜態資料區(data segment)。只初始化一次。

(3)未初始化資料區(bss)。在執行時改變其值。

(4)棧區(stack)。由編譯器自動分配釋放,存放函式的引數值、區域性變數的值等。其操作方式類似於資料結構中的棧。每當乙個函式被呼叫,該函 數返回位址和一些關於呼叫的資訊,比如某些暫存器的內容,被儲存到棧區。然後這個被呼叫的函式再為它的自動變數和臨時變數在棧區上分配空間,這就是c實現 函式遞迴呼叫的方法。每執行一次遞迴函式呼叫,乙個新的棧框架就會被使用,這樣這個新例項棧裡的變數就不會和該函式的另乙個例項棧裡面的變數混淆。

(5)堆區(heap)。用於動態記憶體分配。堆在記憶體中位於bss區和棧區之間。一般由程式設計師分配和釋放,若程式設計師不釋放,程式結束時有可能由os **。

之所以分成這麼多個區域,主要基於以下考慮:

乙個程序在執行過程中,**是根據流程依次執行的,只需要訪問一次,當然跳轉和遞迴有可能使**執行多次,而資料一般都需要訪問多次,因此單獨開闢 空間以方便訪問和節約空間。

臨時資料及需要再次使用的**在執行時放入棧區中,生命周期短。

全域性資料和靜態資料有可能在整個程式執行過程中都需要訪問,因此單獨儲存管理。

堆區由使用者自由分配,以便管理。

下面通過一段簡單的**來檢視c程式執行時的記憶體分配情況。相關資料在執行時的位置如注釋所述。

int a = 0; 

//a在全域性已初始化資料區

char *p1; 

//p1在bss區(未初始化全域性變數)

main()

c 記憶體模型

1 棧區 由編譯器自動分配和釋放,存放函式的引數數值,區域性變數的值 其操作方式類似於資料結構中得棧 2 堆區一般由使用者分配和釋放,若使用者不釋放,程式結束時候由os 它與資料結構中堆是兩回事,分配方式類似鍊錶 3 全域性區 靜態區 static全域性變數和靜態變數的存放區域。初始化的全域性變數和...

C 記憶體模型

1.在c 中,不要在標頭檔案中進行變數宣告。因為單定義規則的存在,不同原始檔中對於同乙個全域性變數只能夠定義一次。因此如果在標頭檔案中包含變數定義,那麼很有可能使用相同標頭檔案的原始檔會對這個變數產生多次定義。2.new 與 delete等通過動態分配記憶體產生的資料將儲存在堆 heap 中。3.在...

C記憶體模型

程式執行時作業系統把磁碟的 load到記憶體,然後分配給該程序乙個記憶體空間,分為堆區,棧區,全域性區和 區如圖1所示。作業系統找到main函式開始執行程式。圖1 記憶體模型 區 存放程式的二進位制 全域性區 全域性變數和靜態變數。初始化的全域性變數和靜態變數在一塊區域,未初始化的全域性變數和未初始...