首先我們來科普一下:
什么是堆蛾派?說到堆俄认,又忍不住說到了棧!什么是 棧洪乍?
1眯杏、什么是堆:堆是大家共有的空間,分全局堆和局部堆壳澳。全局堆就是所有沒有分配的空間岂贩,局部堆就是用戶分配的空間。堆在操作系統(tǒng)對進程 初始化的時候分配巷波,運行過程中也可以向系統(tǒng)要額外的堆萎津,但是記得用完了要還給操作系統(tǒng),要不然就是內(nèi)存泄漏抹镊。 2锉屈、什么是棧:棧是線程獨有的,保存其運行狀態(tài)和局部自動變量的垮耳。棧在線程開始的時候初始化颈渊,每個線程的棧互相獨立氨菇。每個函數(shù)都有自己的棧儡炼,棧被用來在函數(shù)之間傳遞參數(shù)妓湘。操作系統(tǒng)在切換線程的時候會自動的切換棧查蓉,就是切換SS/ESP寄存器。棸裉空間不需要在高級語言里面顯式的分配和釋放豌研。
C語言程序編譯的內(nèi)存分配妹田,堆與棧的區(qū)別:
棧是由編譯器自動分配釋放,存放函數(shù)的參數(shù)值鹃共、局部變量的值等鬼佣。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。 堆一般由程序員分配釋放霜浴,若不釋放晶衷,程序結(jié)束時可能由OS回收。注意這里說是可能阴孟,并非一定晌纫。再強調(diào)一次,記得要釋放永丝!
棧區(qū)(stack) :
//windows下锹漱,棧內(nèi)存分配2M(確定的常數(shù)),超出了限制慕嚷,提示stack overflow錯誤
//編譯器自動分配釋放哥牍,主要存放函數(shù)的參數(shù)值,局部變量值等喝检;
堆區(qū)(heap):程序員手動分配釋放嗅辣,操作系統(tǒng)80%內(nèi)存
全局區(qū)或靜態(tài)區(qū):存放全局變量和靜態(tài)變量;程序結(jié)束時由系統(tǒng)釋放蛇耀,分為全局初始化區(qū)和全局未初始化區(qū)辩诞;
字符常量區(qū):常量字符串放與此,程序結(jié)束時由系統(tǒng)釋放纺涤;
程序代碼區(qū):存放函數(shù)體的二進制代碼译暂。
栗子:
int a=0; //全局初始化區(qū)char p1; //全局未初始化區(qū)void main(){ int b; //棧 char s[]="bb"; //棧 char p2; //棧 char p3="123"; //其中,“123\0”常量區(qū)撩炊,p3在棧區(qū) static int c=0; //全局區(qū) p1=(char)malloc(10); //10個字節(jié)區(qū)域在堆區(qū) strcpy(p1,"123"); //"123\0"在常量區(qū)外永,編譯器 可能 會優(yōu)化為和p3的指向同一塊區(qū)域 }
棧內(nèi)存
void stackFun(){ int a[1024]; //棧內(nèi)存自動釋放}
堆內(nèi)存
void heapFun(){ //40M內(nèi)存 //字節(jié) //void 任意類型的指針 int p = malloc(1024 * 1024 * 10 * sizeof(int)); //釋放 free(p);}
void main(){ //在堆內(nèi)存上,分配40M的內(nèi)存 while (1){ Sleep(1000); stackFun(); } getchar();}
創(chuàng)建一個數(shù)組拧咳,動態(tài)指定數(shù)組的大胁ァ(在程序運行過長中,可以隨意的開辟指定大小的內(nèi)存骆膝,以供使用祭衩,相當于Java中的集合)靜態(tài)內(nèi)存分配,分配內(nèi)存大小的是固定阅签,問題:1.很容易超出棧內(nèi)存的最大值 2.為了防止內(nèi)存不夠用會開辟更多的內(nèi)存掐暮,容易浪費內(nèi)存
動態(tài)內(nèi)存分配,在程序運行過程中政钟,動態(tài)指定需要使用的內(nèi)存大小路克,手動釋放樟结,釋放之后這些內(nèi)存還可以被重新使用(活水)
函數(shù):calloc() 分配內(nèi)存空間并初始化calloc() 函數(shù)用來動態(tài)地分配內(nèi)存空間并初始化為 0,其原型為:
void calloc (size_t num, size_t size);
calloc() 在內(nèi)存中動態(tài)地分配 num 個長度為 size 的連續(xù)空間精算,并將每一個字節(jié)都初始化為 0瓢宦。所以它的結(jié)果是分配了 numsize 個字節(jié)長度的內(nèi)存空間,并且每個字節(jié)的值都是0灰羽。
【返回值】分配成功返回指向該內(nèi)存的地址驮履,失敗則返回 NULL。
函數(shù):malloc() 動態(tài)地分配內(nèi)存空間
malloc() 函數(shù)用來動態(tài)地分配內(nèi)存空間(如果你不了解動態(tài)內(nèi)存分配廉嚼,請查看:C語言動態(tài)內(nèi)存分配及變量存儲類別)疲吸,其原型為:
void* malloc (size_t size);
應(yīng)用在程序中代碼如下:
void main(){ //靜態(tài)內(nèi)存分配創(chuàng)建數(shù)組,數(shù)組的大小是固定的 //int i = 10; //int a[i]; int len; printf("輸入數(shù)組的長度:"); scanf("%d",&len); //開辟內(nèi)存前鹅,大小len4字節(jié) int p = malloc(len * sizeof(int)); //p是數(shù)組的首地址摘悴,p就是數(shù)組的名稱 //給數(shù)組元素賦值(使用這一塊剛剛開辟出來的內(nèi)存區(qū)域) int i = 0; for (; i < len - 1; i++){ p[i] = rand() % 100; printf("%d,%#x\n", p[i], &p[i]); } //手動釋放內(nèi)存 //free()釋放動態(tài)分配的內(nèi)存空間 free(p); getchar();}
realloc 重新分配內(nèi)存
void main(){ int len; printf("第一次輸入數(shù)組的長度:"); scanf("%d", &len); //int* p = malloc(len * sizeof(int)); int* p = calloc(len, sizeof(int)); int i = 0; for (; i < len; i++){ p[i] = rand() % 100; printf("%d,%#x\n", p[i], &p[i]); } int addLen; printf("輸入數(shù)組增加的長度:"); scanf("%d", &addLen); //內(nèi)存不夠用,擴大剛剛分配的內(nèi)存空間 //1.原來內(nèi)存的指針 2.內(nèi)存擴大之后的總大小 int* p2 = realloc(p, sizeof(int) * (len + addLen)); if (p2 == NULL){ printf("重新分配失敗舰绘,世界那么大蹂喻,容不下我。捂寿。口四。"); }
新分配內(nèi)存的兩種情況:
//縮小,縮小的那一部分數(shù)據(jù)會丟失
//擴大秦陋,(連續(xù)的)1.如果當前內(nèi)存段后面有需要的內(nèi)存空間蔓彩,直接擴展這段內(nèi)存空間,realloc返回原指針2.如果當前內(nèi)存段后面的空閑字節(jié)不夠驳概,那么就使用堆中的第一個能夠滿足這一要求的內(nèi)存塊赤嚼,將目前的數(shù)據(jù)復(fù)制到新的位置拜效,并將原來的數(shù)據(jù)庫釋放掉漓骚,返回新的內(nèi)存地址3.如果申請失敗蛙埂,返回NULL灌侣,原來的指針仍然有效
//接著上面的代碼重新賦值 i = 0; printf("--------------------------\n"); for (; i < len + addLen; i++){ p2[i] = rand() % 200; printf("%d,%#x\n", p2[i], &p2[i]); } //手動釋放內(nèi)存 if (p != NULL){ free(p); p = NULL; } if (p2 != NULL){ free(p2); p2 = NULL; } getchar();}
內(nèi)存分配的幾個注意細節(jié)
1.不能多次釋放;2.釋放完之后(指針仍然有值)鲫忍,給指針置NULL舰始,標志釋放完成第焰;3.內(nèi)存泄露(p重新賦值之后果录,再free上枕,并沒有真正釋放內(nèi)存);
void main(){
int len;
printf("輸入數(shù)組的長度:");
scanf("%d", &len);
?
int* p = malloc(len * sizeof(int));
int i = 0;
for (; i < len; i++){
p[i] = rand() % 100;
printf("%d,%#x\n", p[i], &p[i]);
}
?
if (p != NULL){
free(p);
p = NULL;
}
?
getchar();
}
以上就是C語言中對內(nèi)存的分配與釋放弱恒,常用的幾個函數(shù)~
學(xué)習(xí)理解并整理下來的筆記辨萍。希望大家能夠指點或提出寶貴意見,謝謝斤彼!一起學(xué)習(xí)分瘦。轉(zhuǎn)載請注明出處:http://blog.csdn.net/u011974987/article/details/52290724 個人站點:xuhao.tech