c 記憶體分配詳解

2021-06-18 16:02:55 字數 3432 閱讀 3145

c語言可執行**結構

名稱內容

**段可執行**、字串常量

資料段已初始化全域性變數、已初始化全域性靜態變數、區域性靜態變數、常量資料

bss段

未初始化全域性變數,未初始化全域性靜態變數

棧區域性變數、函式引數

堆動態記憶體分配

一般情況下,乙個可執行二進位制程式(更確切的說,在linux作業系統下為乙個程序單元,在uc/osii中被稱為任務)在儲存(沒有調入到記憶體執行)時擁有3個部分,分別是**段(text)、資料段(data)和bss段。這3個部分一起組成了該可執行程式的檔案。

(1)**段(text segment):存放cpu執行的機器指令。通常**段是可共享的,這使得需要頻繁被執行的程式只需要在記憶體中擁有乙份拷貝即可。**段也通常是唯讀的,這樣可以防止其他程式意外地修改其指令。另外,**段還規劃了區域性資料所申請的記憶體空間資訊。

**段(code segment/text segment)通常是指用來存放程式執行**的一塊記憶體區域。這部分區域的大小在程式執行前就已經確定,並且記憶體區域通常屬於唯讀, 某些架構也允許**段為可寫,即允許修改程式。在**段中,也有可能包含一些唯讀的常數變數,例如字串常量等。

(2)資料段(data segment):或稱全域性初始化資料段/靜態資料段(initialized data segment/data segment)。該段包含了在程式中明確被初始化的全域性變數、靜態變數(包括全域性靜態變數和區域性靜態變數)和常量資料。

(3)未初始化資料段:亦稱bss(block started by symbol)。該段存入的是全域性未初始化變數、靜態未初始化變數。

而當程式被載入到記憶體單元時,則需要另外兩個域:堆域和棧域。

(4)棧段(stack):存放函式的引數值、區域性變數的值,以及在進行任務切換時存放當前任務的上下文內容。

(5)堆段(heap):用於動態記憶體分配,即使用malloc/free系列函式來管理的記憶體空間。

在將應用程式載入到記憶體空間執行時,作業系統負責**段、資料段和bss段的載入,並將在記憶體中為這些段分配空間。棧段亦由作業系統分配和管理,而不需要程式設計師顯示地管理;堆段由程式設計師自己管理,即顯示地申請和釋放空間。

另外,可執行程式在執行時具有相應的程式屬性。在有作業系統支援時,這些屬性頁由作業系統管理和維護。

下面給出示例程式**,注釋已經在**中寫明:

[cpp]

view plain

copy

print?

/***段、資料段和bss段儲存變數型別*/

#include 

const

intg_a       = 10;            

//**段

intg_b       = 20;            

//資料段

static

intg_c       = 30;            

//資料段

static

intg_d;                    

//bss段

intg_e;                    

//bss段

char

*p1;                    

//bss段

void

main( )  

放在常量區,編譯器可能會將它與p3所指向 的"123456"優化成一塊

printf("\n"

);  

printf( "**段,全域性初始化變數, 唯讀const,  g_a,     addr:0x%08x\n"

, &g_a);  

printf("\n"

);  

printf( "資料段,全域性變數,       初始化      g_b,     addr:0x%08x\n"

, &g_b);  

printf( "資料段,靜態全域性變數,   初始化,     g_c,     addr:0x%08x\n"

, &g_c);  

printf("\n"

);  

printf( "bss段, 全域性變數,       未初始化    g_e,     addr:0x%08x\n"

, &g_e, g_e );      

printf( "bss段, 靜態全域性變數,   未初始化,   g_d,     addr:0x%08x\n"

, &g_d );  

printf( "bss段, 靜態區域性變數,   初始化,     local_c, addr:0x%08x\n"

, &local_c);  

printf( "bss段, 靜態區域性變數,   未初始化,   local_d, addr:0x%08x\n"

, &local_d);  

printf("\n"

);  

printf( "棧,    區域性變數,                   local_a, addr:0x%08x\n"

, &local_a );  

printf("\n"

);  

printf( "堆,    malloc分配記憶體,             p1,      addr:0x%08x\n"

, p1 );  

}  預備知識—程式的記憶體分配

乙個由c/c++編譯的程式占用的記憶體分為以下幾個部分

1、棧區(stack)— 由

編譯器自動分配釋放

,存放函式的引數值,區域性變數的值等。其操作方式類似於資料結構中的棧。

2、堆區(heap) —

一般由程式設計師分配釋放

, 若程式設計師不釋放,程式結束時可能由os** 。注意它與資料結構中的堆是兩回事,分配方式倒是類似於鍊錶,呵呵。

3、全域性區(靜態區)(static)—,全域性變數和靜態變數的儲存是放在一塊的,初始化的全域性變數和靜態變數在一塊區域, 未初始化的全域性變數和未初始化的靜態變數在相鄰的另一塊區域。 - 程式結束後有系統釋放

4、文字常量區 —常量字串就是放在這裡的。 程式結束後由系統釋放

5、程式**區—存放函式體的二進位制**。

乙個正常的程式在記憶體中通常分為程式段,資料端和堆疊三部分。

程式段裡放著程式的機器碼和唯讀資料,這個段通常是唯讀

,對它的寫操作是非法的。

資料段放的是程式中的靜態資料

。動態資料則通過堆疊來存放

。在記憶體中,它們的位置如下:

+------------------+ 記憶體低端

| 程式段 |

|------------------|

| 資料段 |

|------------------|

| 堆  棧  |

+------------------+ 記憶體高階

**段,唯讀資料段(常量,字面值,const宣告的變數),已初始化可讀寫資料段(已初始化靜態和全域性變數),未初始化可讀寫資料段(未初始化靜態和全域性變數),棧,堆

c 記憶體分配詳解

一 c c 記憶體分配的5個區分別是 棧區 堆區 全域性區 靜態區 文字常量區 程式 區 1 棧區 編輯器自動分配 和 釋放,存放函式的引數,區域性變數等。2 堆區 一般是程式設計師分配和釋放,如果在程式一直執行的狀態下,程式設計師不去釋放記憶體,會導致記憶體洩漏之後會打到一定程度的時候會導致系統崩...

C 中記憶體分配詳解

程式執行時,特別要注意的是記憶體的分配。下面介紹c 程式設計中的記憶體分配。一 記憶體基本構成 可程式設計內存在基本上分為這樣的幾大部分 靜態儲存區 堆區和棧區。他們的功能不同,對他們使用方式也就不同。靜態儲存區 內存在程式編譯的時候就已經分配好,這塊內存在程式的整個執行期間都存在。它主要存放靜態資...

C 程式記憶體分配詳解

1.硬碟中的結構 程式 首先在linux下檢視一下test檔案的資訊 root localhost ctest file test 此檔案基本情況 test elf 32 bit lsb executable,intel 80386,version 1 sysv for gnu linux 2.2....