新(xīn)疆軟件開發

本站首頁(yè) 軟件開發 成功案例 公(gōng)司新(xīn)聞 公(gōng)司簡介 客服中(zhōng)心 軟件技(jì )術 網站建設
  您現在的位置: 新(xīn)疆二域軟件開發公(gōng)司 >> 開發語言 >> 文(wén)章正文(wén)

Heap和Stack的區(qū)别在那裏

一、預備知識—程序的内存分(fēn)配 
一個由c/C++編譯的程序占用(yòng)的内存分(fēn)為(wèi)以下幾個部分(fēn) 
1、棧區(qū)(stack)— 由編譯器自動分(fēn)配釋放 ,存放函數的參數值,局部變量的值等。其操作(zuò)方式類似于數據結構中(zhōng)的棧。 
2、堆區(qū)(heap) — 一般由程序員分(fēn)配釋放, 若程序員不釋放,程序結束時可(kě)能(néng)由OS回收 。注意它與數據結構中(zhōng)的堆是兩回事,分(fēn)配方式倒是類似于鏈表,呵呵。 
3、全局區(qū)(靜态區(qū))(static)—,全局變量和靜态變量的存儲是放在一塊的,初始化的全局變量和靜态變量在一塊區(qū)域, 未初始化的全局變量和未初始化的靜态變量在相鄰的另一塊區(qū)域。 - 程序結束後有(yǒu)系統釋放 
4、文(wén)字常量區(qū) —常量字符串就是放在這裏的。 程序結束後由系統釋放 
5、程序代碼區(qū)—存放函數體(tǐ)的二進制代碼。 

二、例子程序  新(xīn)疆軟件開發網
這是一個前輩寫的,非常詳細 
//main.cpp 
int a = 0; 全局初始化區(qū) 
char *p1; 全局未初始化區(qū) 
main() 

int b; 棧 
char s[] = "abc"; 棧 
char *p2; 棧 
char *p3 = "123456"; 123456\0在常量區(qū),p3在棧上。 
static int c =0; 全局(靜态)初始化區(qū) 
p1 = (char *)malloc(10); 
p2 = (char *)malloc(20); 
分(fēn)配得來得10和20字節的區(qū)域就在堆區(qū)。 
strcpy(p1, "123456"); 123456\0放在常量區(qū),編譯器可(kě)能(néng)會将它與p3所指向的"123456"優化成一個地方。 
}  
二、堆和棧的理(lǐ)論知識 
2.1申請方式 
stack: 
由系統自動分(fēn)配。 例如,聲明在函數中(zhōng)一個局部變量 int b; 系統自動在棧中(zhōng)為(wèi)b開辟空間 
heap: 
需要程序員自己申請,并指明大小(xiǎo),在c中(zhōng)malloc函數 
如p1 = (char *)malloc(10); 
在C++中(zhōng)用(yòng)new運算符 
如p2 = (char *)malloc(10); 
但是注意p1、p2本身是在棧中(zhōng)的。 
2.2 
申請後系統的響應 
棧:隻要棧的剩餘空間大于所申請空間,系統将為(wèi)程序提供内存,否則将報異常提示棧溢出。 
堆:首先應該知道操作(zuò)系統有(yǒu)一個記錄空閑内存地址的鏈表,當系統收到程序的申請時, 
會遍曆該鏈表,尋找第一個空間大于所申請空間的堆結點,然後将該結點從空閑結點鏈表中(zhōng)删除,并将該結點的空間分(fēn)配給程序,另外,對于大多(duō)數系統,會在這塊内存空間中(zhōng)的首地址處記錄本次分(fēn)配的大小(xiǎo),這樣,代碼中(zhōng)的delete語句才能(néng)正确的釋放本内存空間。另外,由于找到的堆結點的大小(xiǎo)不一定正好等于申請的大小(xiǎo),系統會自動的将多(duō)餘的那部分(fēn)重新(xīn)放入空閑鏈表中(zhōng)。 
2.3申請大小(xiǎo)的限制 
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的内存的區(qū)域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在 WINDOWS下,棧的大小(xiǎo)是2M(也有(yǒu)的說是1M,總之是一個編譯時就确定的常數),如果申請的空間超過棧的剩餘空間時,将提示overflow。因此,能(néng)從棧獲得的空間較小(xiǎo)。 
堆:堆是向高地址擴展的數據結構,是不連續的内存區(qū)域。這是由于系統是用(yòng)鏈表來存儲的空閑内存地址的,自然是不連續的,而鏈表的遍曆方向是由低地址向高地址。堆的大小(xiǎo)受限于計算機系統中(zhōng)有(yǒu)效的虛拟内存。由此可(kě)見,堆獲得的空間比較靈活,也比較大。 
2.4申請效率的比較: 
棧由系統自動分(fēn)配,速度較快。但程序員是無法控制的。 
堆是由new分(fēn)配的内存,一般速度比較慢,而且容易産(chǎn)生内存碎片,不過用(yòng)起來最方便. 
另外,在WINDOWS下,最好的方式是用(yòng)VirtualAlloc分(fēn)配内存,他(tā)不是在堆,也不是在棧是直接在進程的地址空間中(zhōng)保留一快内存,雖然用(yòng)起來最不方便。但是速度快,也最靈活 
2.5堆和棧中(zhōng)的存儲内容 
棧: 在函數調用(yòng)時,第一個進棧的是主函數中(zhōng)後的下一條指令(函數調用(yòng)語句的下一條可(kě)執行語句)的地址,然後是函數的各個參數,在大多(duō)數的C編譯器中(zhōng),參數是由右往左入棧的,然後是函數中(zhōng)的局部變量。注意靜态變量是不入棧的。 
當本次函數調用(yòng)結束後,局部變量先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中(zhōng)的下一條指令,程序由該點繼續運行。 
堆:一般是在堆的頭部用(yòng)一個字節存放堆的大小(xiǎo)。堆中(zhōng)的具(jù)體(tǐ)内容有(yǒu)程序員安(ān)排。 
2.6存取效率的比較 

char s1[] = "aaaaaaaaaaaaaaa"; 
char *s2 = "bbbbbbbbbbbbbbbbb"; 
aaaaaaaaaaa是在運行時刻賦值的; 
而bbbbbbbbbbb是在編譯時就确定的; 
但是,在以後的存取中(zhōng),在棧上的數組比指針所指向的字符串(例如堆)快。 
比如: 
#include <stdio.h>; 
void main() 

char a = 1; 
char c[] = "1234567890"; 
char *p ="1234567890"; 
a = c[1]; 
a = p[1]; 
return; 

對應的彙編代碼 
10: a = c[1]; 
00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh] 
0040106A 88 4D FC mov byte ptr [ebp-4],cl 
11: a = p[1]; 
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h] 
00401070 8A 42 01 mov al,byte ptr [edx+1] 
00401073 88 45 FC mov byte ptr [ebp-4],al 
第一種在讀取時直接就把字符串中(zhōng)的元素讀到寄存器cl中(zhōng),而第二種則要先把指針值讀到edx中(zhōng),在根據edx讀取字符,顯然慢了。 
?  

2.7小(xiǎo)結: 
堆和棧的區(qū)别可(kě)以用(yòng)如下的比喻來看出: 
使用(yòng)棧就象我們去飯館裏吃飯,隻管點菜(發出申請)、付錢、和吃(使用(yòng)),吃飽了就走,不必理(lǐ)會切菜、洗菜等準備工(gōng)作(zuò)和洗碗、刷鍋等掃尾工(gōng)作(zuò),他(tā)的好處是快捷,但是自由度小(xiǎo)。 
使用(yòng)堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。
堆和棧的區(qū)别主要分(fēn): 
操作(zuò)系統方面的堆和棧,如上面說的那些,不多(duō)說了。 
還有(yǒu)就是數據結構方面的堆和棧,這些都是不同的概念。這裏的堆實際上指的就是(滿足堆性質(zhì)的)優先隊列的一種數據結構,第1個元素有(yǒu)最高的優先權;棧實際上就是滿足先進後出的性質(zhì)的數學(xué)或數據結構。 
雖然堆棧,堆棧的說法是連起來叫,但是他(tā)們還是有(yǒu)很(hěn)大區(qū)别的,連着叫隻是由于曆史的原因。

作(zuò)者:未知 | 文(wén)章來源:未知 | 更新(xīn)時間:2007-12-3 14:26:42

  • 上一篇文(wén)章:

  • 下一篇文(wén)章:

  • 相關文(wén)章:
    沒有(yǒu)相關文(wén)章
    軟件技(jì )術
    · 開發語言
    · Java技(jì )術
    · .Net技(jì )術
    · 數據庫開發
    最新(xīn)文(wén)章  
    ·搜集整理(lǐ)的asp.net的驗證方
    ·各種FOR循環結構的整理(lǐ)
    ·軟件項目開發中(zhōng)應該考慮那
    ·搜集整理(lǐ)的javascript sel
    ·軟件開發中(zhōng)項目經理(lǐ)有(yǒu)那些
    ·學(xué)習如何在Lambda表達式進
    ·C++基礎知識:結構體(tǐ)數據的
    ·C#實現短信發送程序的例子
    ·sun最近修補了一部分(fēn)java的
    ·rss定制的另外一種實現方式
    ·delphi實現利用(yòng)arp欺騙來實
    ·基礎學(xué)習:基于WF的流程框
    ·網絡編程中(zhōng)怎樣得知一次數
    ·如何逆序輸出單鏈表?
    ·軟件開發過程中(zhōng)的性能(néng)設計
    關于我們 | 軟件開發 | 下載試用(yòng) | 客服中(zhōng)心 | 聯系我們 | 友情鏈接 | 網站地圖 | 新(xīn)疆電(diàn)子地圖 |
    版權所有(yǒu) © 2016 新(xīn)疆二域軟件開發網 www.k8w.net All Rights Reserved 新(xīn)ICP備14003571号
    新(xīn)疆軟件開發總機:0991-4842803、4811639.
    客服QQ:596589785 ;地址:新(xīn)疆烏魯木(mù)齊北京中(zhōng)路華聯大廈A-5C 郵編:830000