C 資料儲存區

2021-08-01 19:58:54 字數 3398 閱讀 7018

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

棧(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 初始化的全域性 靜態區域 全域性變數和靜態變數的儲存是放在一塊的...