深入C語言內(nèi)存區(qū)域分配(進(jìn)程的各個(gè)段)詳解
| 名稱 | 內(nèi)容 |
| 代碼段 | 可執(zhí)行代碼、字符串常量 |
| 數(shù)據(jù)段 | 已初始化全局變量、已初始化全局靜態(tài)變量、局部靜態(tài)變量、常量數(shù)據(jù) |
| BSS段 | 未初始化全局變量,未初始化全局靜態(tài)變量 |
| 棧 | 局部變量、函數(shù)參數(shù) |
| 堆 | 動(dòng)態(tài)內(nèi)存分配 |
(1)代碼段(text segment):存放CPU執(zhí)行的機(jī)器指令。通常代碼段是可共享的,這使得需要頻繁被執(zhí)行的程序只需要在內(nèi)存中擁有一份拷貝即可。代碼段也通常是只讀的,這樣可以防止其他程序意外地修改其指令。另外,代碼段還規(guī)劃了局部數(shù)據(jù)所申請(qǐng)的內(nèi)存空間信息。
代碼段(code segment/text segment)通常是指用來存放程序執(zhí)行代碼的一塊內(nèi)存區(qū)域。這部分區(qū)域的大小在程序運(yùn)行前就已經(jīng)確定,并且內(nèi)存區(qū)域通常屬于只讀, 某些架構(gòu)也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數(shù)變量,例如字符串常量等。
(2)數(shù)據(jù)段(data segment):或稱全局初始化數(shù)據(jù)段/靜態(tài)數(shù)據(jù)段(initialized data segment/data segment)。該段包含了在程序中明確被初始化的全局變量、靜態(tài)變量(包括全局靜態(tài)變量和局部靜態(tài)變量)和常量數(shù)據(jù)。
(3)未初始化數(shù)據(jù)段:亦稱BSS(Block Started by Symbol)。該段存入的是全局未初始化變量、靜態(tài)未初始化變量。
而當(dāng)程序被加載到內(nèi)存單元時(shí),則需要另外兩個(gè)域:堆域和棧域。
(4)棧段(stack):存放函數(shù)的參數(shù)值、局部變量的值,以及在進(jìn)行任務(wù)切換時(shí)存放當(dāng)前任務(wù)的上下文內(nèi)容。
(5)堆段(heap):用于動(dòng)態(tài)內(nèi)存分配,即使用malloc/free系列函數(shù)來管理的內(nèi)存空間。
在將應(yīng)用程序加載到內(nèi)存空間執(zhí)行時(shí),操作系統(tǒng)負(fù)責(zé)代碼段、數(shù)據(jù)段和BSS段的加載,并將在內(nèi)存中為這些段分配空間。棧段亦由操作系統(tǒng)分配和管理,而不需要程序員顯示地管理;堆段由程序員自己管理,即顯示地申請(qǐng)和釋放空間。
另外,可執(zhí)行程序在運(yùn)行時(shí)具有相應(yīng)的程序?qū)傩?。在有操作系統(tǒng)支持時(shí),這些屬性頁由操作系統(tǒng)管理和維護(hù)。
下面給出示例程序代碼,注釋已經(jīng)在代碼中寫明:
/*代碼段、數(shù)據(jù)段和BSS段存儲(chǔ)變量類型*/
#include <stdio.h>
const int g_A = 10; //代碼段
int g_B = 20; //數(shù)據(jù)段
static int g_C = 30; //數(shù)據(jù)段
static int g_D; //BSS段
int g_E; //BSS段
char *p1; //BSS段
void main( )
{
int local_A; //棧
static int local_C = 0; //數(shù)據(jù)段
static int local_D; //數(shù)據(jù)段
char *p3 = "123456"; //123456在代碼段,p3在棧上
p1 = (char *)malloc( 10 ); //堆,分配得來得10字節(jié)的區(qū)域在堆區(qū)
strcpy( p1, "123456" ); //123456{post.content}放在常量區(qū),編譯器可能會(huì)將它與p3所指向 的"123456"優(yōu)化成一塊
printf("\n");
printf( "代碼段,全局初始化變量, 只讀const, g_A, addr:0x%08x\n", &g_A);
printf("\n");
printf( "數(shù)據(jù)段,全局變量, 初始化 g_B, addr:0x%08x\n", &g_B);
printf( "數(shù)據(jù)段,靜態(tài)全局變量, 初始化, g_C, addr:0x%08x\n", &g_C);
printf("\n");
printf( "BSS段, 全局變量, 未初始化 g_E, addr:0x%08x\n", &g_E, g_E );
printf( "BSS段, 靜態(tài)全局變量, 未初始化, g_D, addr:0x%08x\n", &g_D );
printf( "BSS段, 靜態(tài)局部變量, 初始化, local_C, addr:0x%08x\n", &local_C);
printf( "BSS段, 靜態(tài)局部變量, 未初始化, local_D, addr:0x%08x\n", &local_D);
printf("\n");
printf( "棧, 局部變量, local_A, addr:0x%08x\n", &local_A );
printf("\n");
printf( "堆, malloc分配內(nèi)存, p1, addr:0x%08x\n", p1 );
}
相關(guān)文章
C語言數(shù)據(jù)結(jié)構(gòu)之隊(duì)列的定義與實(shí)現(xiàn)
隊(duì)列是一種特殊的線性表,特殊之處在于它只允許在表的前端(head)進(jìn)行刪除操作,而在表的后端(tail)進(jìn)行插入操作。本文將詳細(xì)講講C語言中隊(duì)列的定義與實(shí)現(xiàn),感興趣的可以了解一下2022-07-07
關(guān)于C++智能指針shared_ptr和unique_ptr能否互轉(zhuǎn)問題
C++中的智能指針最常用的是shared_ptr和unique_ptr,C++新手最常問的問題是我從一個(gè)函數(shù)中拿到unique_ptr,但要轉(zhuǎn)成shared_ptr才能使用,要怎么轉(zhuǎn)換?同理是否能將shared_ptr轉(zhuǎn)換成unique_ptr,面對(duì)這些問題,跟隨小編一起看看吧2022-05-05
visual?studio?2022?編譯出來的文件被刪除并監(jiān)視目錄中的文件變更(示例詳解)
這篇文章主要介紹了visual?studio?2022?編譯出來的文件被刪除?并監(jiān)視目錄中的文件變更,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-08-08
C語言詳細(xì)分析宏定義與預(yù)處理命令的應(yīng)用
宏定義是用宏名來表示一個(gè)字符串,在宏展開時(shí)又以該字符串取代宏名,這只是一種簡(jiǎn)單的替換。字符串中可以含任何字符,可以是常數(shù),也可以是表達(dá)式,預(yù)處理程序?qū)λ蛔魅魏螜z查,如有錯(cuò)誤,只能在編譯已被宏展開后的源程序時(shí)發(fā)現(xiàn)2022-07-07
C++中實(shí)現(xiàn)子進(jìn)程執(zhí)行和管道通信詳解
在這篇博客中,我們將深入探索如何在 C++ 程序中實(shí)現(xiàn)子進(jìn)程的創(chuàng)建與執(zhí)行,以及父子進(jìn)程間的管道通信,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-01-01

