一、 在c中分為這幾個存儲區
內存區域 |
存放內容 |
釋放時間 |
棧 |
在函數體中定義的變量通常是在棧上 |
由編譯器自動分配釋放 |
堆 |
用malloc, calloc, realloc等分配內存的函數分配得到的就是在堆上 |
一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收 |
全局區(靜態區) |
全局變量和靜態變量的存儲是放在一塊的,初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另一塊區域。 |
程序結束釋放 |
常量區域 |
函數中的"adgfdf"這樣的字符串存放在常量區 |
程序結束釋放 |
程序代碼區 |
存放二進制代碼 |
/ |
注意:在所有函數體外定義的是全局量,加了static修飾符后不管在哪里都存放在全局區(靜態區),在所有函數體外定義的static變量表示在該文件中有效,不能extern到別的文件用,在函數體內定義的static表示只在該函數體內有效。
int a = 0; //全局初始化區
char *p1; //全局未初始化區
void main() {
int b; //棧
char s[] = "abc"; //棧
char *p2; //棧
char *p3 = "123456"; / /123456{post.content}在常量區,p3在棧上
static int c = 0; //全局(靜態)初始化區
p1 = (char *)malloc(10); //分配得來得10字節的區域在堆區
p2 = (char *)malloc(20); //分配得來得20字節的區域在堆區
strcpy(p1, "123456"); //123456{post.content}放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一塊
}
堆 |
棧 |
是系統提供的功能,特點是快速高效,缺點是有限制,數據不靈活 |
是函數庫提供的功能,特點是靈活方便,數據適應面廣泛,但是效率有一定降低 |
棧是系統數據結構,對于進程/線程是唯一的 |
堆是函數庫內部數據結構,不一定唯一;不同堆分配的內存無法互相操作; |
??臻g分靜態分配和動態分配兩種。靜態分配是編譯器完成的,比如自動變量(auto)的分配。動態分配由alloca函數完成。棧的動態分配無需釋放(是自動的),也就沒有釋放函數。為可移植的程序起見,棧的動態分配操作是不被鼓勵的 |
堆空間的分配總是動態的,雖然程序結束時所有的數據空間都會被釋放回系統,但是精確的申請內存 |
、 |
堆 |
棧 |
碎片問題 |
對于堆來講,頻繁的new/delete勢必會造成內存空間的不連續,從而造成大量的碎片,使程序效率降低 |
對于棧來講,則不會存在這個問題,因為棧是先進后出的隊列,他們是如此的一一對應,以至于永遠都不可能有一個內存塊從棧中間彈出,在他彈出之前,在他上面的后進的棧內容已經被彈出 |
生長方向 |
生長方向是向上的,也就是向著內存地址增加的方向 |
生長方向是向下的,是向著內存地址減小的方向增長 |
分配方式 |
堆都是動態分配的,沒有靜態分配的堆 |
棧有2種分配方式:靜態分配和動態分配。靜態分配是編譯器完成的,比如局部變量的分配。動態分配由alloca函數進行分配,但是棧的動態分配和堆是不同的,他的動態分配是由編譯器進行釋放,無需我們手工實現 |
分配效率 |
棧是機器系統提供的數據結構,計算機會在底層對棧提供支持:分配專門的寄存器存放棧的地址,壓棧出棧都有專門的指令執行,這就決定了棧的效率比較高 |
堆則是C/C++函數庫提供的,它的機制是很復雜的,例如為了分配一塊內存,庫函數會按照一定的算法(具體的算法可以參考數據結構/操作系統)在堆內存中搜索可用的足夠大小的空間,如果沒有足夠大小的空間(可能是由于內存碎片太多),就有可能調用系統功能去增加程序數據段的內存空間,這樣就有機會分到足夠大小的內存,然后進行返回。顯然,堆的效率比棧要低得多 |