**段(也稱文字段):用來存放程式執行**的記憶體區。這部分區域的大小在程式執行前就已經確定,並且記憶體區域通常屬於唯讀, 某些架構也允許**段為可寫,即允許修改程式。在**段中,也有可能包含一些唯讀的常數變數,例如字串常量等。
棧(stack):
就是那些由編譯器在需要的時候分配,在不需要的時候自動清除的變數的儲存區。裡面的變數通常是區域性變數、函式引數等。
堆(heap):
一般由程式設計師分配釋放,
若程式設計師不釋放,程式結束時可能由
os**。
常量儲存區,常量字串就是放在這裡的,不允許修改
(通過非正當手段也可以修改,而且方法很多
),程式結束後由系統釋放。
資料段:存放程式中已初始化的全域性變數。
bss段:存放程式中為初始化的全域性變數和靜態變數。在程式執行之前會被自動清零,所以這也是為初始化的全域性變數為什麼會自動為0的原因。
int a = 0; //全域性初始化區
char *p1; //全域性未初始化區
void main()
在常量區,p3在棧上
static int c = 0; //全域性(靜態)初始化區
p1 = (char *)malloc(10); //分配得來得10位元組的區域在堆區
p2 = (char *)malloc(20); //分配得來得20位元組的區域在堆區
strcpy(p1, "123456");
//123456放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一塊
}
|----------------------|
| 核心虛擬儲存器 |
|----------------------|
| 使用者棧(statk) |
|----------------------|
| | |
| / / |
| |
| / / |
| | |
|----------------------|
| 堆(heap) |
|----------------------|
| 未初始化(bss) |
|----------------------|
| 初始化(data) |
|----------------------|
| 正文段(text |
|----------------------|
區分堆與棧
:
void f()
這條短短的一句話就包含了堆與棧,關鍵
new指示分配了一塊堆記憶體,而指標
p分配的是一塊棧記憶體,所以這句話的意思就是:在棧記憶體中存放了乙個指向一塊堆記憶體的指標
p。在程式會先確定在堆中分配記憶體的大小,然後呼叫
operator new
分配記憶體,然後返回這塊記憶體的首位址,放入棧中,他在
vc6下的彙編**如下:
00401028 push 14h
0040102a call operator new (00401060)
0040102f add esp,4
00401032 mov dword ptr [ebp-8],eax
00401035 mov eax,dword ptr [ebp-8]
00401038 mov dword ptr [ebp-4],eax
堆與棧主要的區別由以下幾點:
1)管理方式:對於棧來講,是由編譯器自動管理,無需手動控制;對於堆來說,釋放工作由程式設計師控制,容易產生記憶體洩露。
2)申請後系統的響應:對於棧來講,只要棧的剩餘空間大於所申請空間,系統將為程式提供記憶體,否則將報異常提示棧溢位。對於堆來講,首先應該知道作業系統有乙個記錄空閒記憶體位址的鍊錶,當系統收到程式的申請時,會遍歷該鍊錶,尋找第乙個空間大於所申請空間的堆結點,然後將該結點從空閒結點鍊錶中刪除,並將剩餘的部分重新放入空閒鍊錶中,最後將該結點的空間分配給程式。另外,對於大多數系統,會在這塊記憶體空間中的首位址處記錄本次分配的大小,這樣**中的
delete
語句才能正確的釋放本記憶體空間。 3
)空間大小:堆的大小受限於計算機系統中有效的虛擬記憶體。一般來講在
32位系統下,堆記憶體可以達到
4g的空間,從這個角度來看堆記憶體幾乎是沒有什麼限制的。但是對於棧來講,一般都是有一定的空間大小的,例如,在
vc6下面,預設的棧空間大小是
1m。兩個引數都可以修改:
project->setting->link
,在category
中選中output
,然後在
reserve
中設定堆疊的最大值和
commit
。注意:
reserve
最小值為
4byte
;commit
是保留在虛擬記憶體的頁檔案裡面,它設定的較大會使棧開闢較大的值,可能增加記憶體的開銷和啟動時間。
4)碎片問題:對於堆來講,頻繁的
new/delete
勢必會造成記憶體空間的不連續,從而造成大量的碎片,使程式效率降低。對於棧來講,則不會存在這個問題。
5)生長方向:對於堆來講,生長方向是向上的,也就是向著記憶體位址增加的方向;對於棧來講,它的生長方向是向下的,是向著記憶體位址減小的方向增長。()
6)分配效率:棧是機器系統提供的資料結構,計算機會在底層對棧提供支援:分配專門的暫存器存放棧的位址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高。堆則是
c/c++
函式庫提供的,它的機制是很複雜的,例如為了分配一塊記憶體,庫函式會按照一定的演算法,在堆記憶體中搜尋可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由於記憶體碎片太多),就有可能呼叫系統功能去增加程式資料段的記憶體空間,這樣就有機會分到足夠大小的記憶體,然後進行返回。顯然,堆的效率比棧要低得多。另外,在
windows
下,最好的方式是用
virtualalloc
分配記憶體,它不是在堆,也不是在棧,而是直接在程序的位址空間中保留一快記憶體,雖然用起來最不方便。但是速度快,也最靈活。
總之,堆和棧相比,由於大量
new/delete
的使用,容易造成大量的記憶體碎片;由於沒有專門的系統支援,效率很低;由於可能引發使用者態和核心態的切換,記憶體的申請,代價變得更加昂貴。
頂
C語言的資料儲存區
c語言分為4個儲存區域 區靜態儲存區 棧區堆區 區 存放編譯後的可執行 的區域。靜態儲存區 儲存著靜態變數 static修飾的變數 如 static int a 和一些常量 如 char p abcd 其中的 abcd 就是儲存在靜態儲存區的 並且被認為是唯讀的 以及全域性變數 全域性變數和靜態變數...
c語言儲存區 堆疊靜態儲存區
棧 由編譯器自動分配釋放,其中存放在主調函式中被呼叫函式的下一句 函式引數和區域性變數,容量有限 堆由程式設計師自己分配釋放 用malloc和free,或new和delete 如果我們不手動釋放,那就要到程式結束才釋放。如果對分配的空間在不用的時候不釋放而一味的分配,那麼可能會引起記憶體洩漏,其容量...
C的儲存區
1 概述 在c中一般分為這幾個儲存區 1 段區域 code segment 放置程式 的區域,沒有什麼好多說的 2 常量區域 放置程式中的常量,如以const作為字首定義的,中形如 abcdef 的字串,該區域內存在程式結束時釋放 3 初始化的全域性 靜態區域 全域性變數和靜態變數的儲存是放在一塊的...