C語言內(nèi)存分配與釋放

首先我們來科普一下:

什么是堆蛾派?說到堆俄认,又忍不住說到了棧!什么是 棧洪乍?
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é)果是分配了 num
size 個字節(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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市琉苇,隨后出現(xiàn)的幾起案子嘲玫,更是在濱河造成了極大的恐慌,老刑警劉巖并扇,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件去团,死亡現(xiàn)場離奇詭異,居然都是意外死亡穷蛹,警方通過查閱死者的電腦和手機土陪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肴熏,“玉大人鬼雀,你說我怎么就攤上這事⊥芾簦” “怎么了源哩?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鸦做。 經(jīng)常有香客問我励烦,道長,這世上最難降的妖魔是什么泼诱? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任坛掠,我火速辦了婚禮,結(jié)果婚禮上治筒,老公的妹妹穿的比我還像新娘屉栓。我一直安慰自己,他們只是感情好耸袜,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布系瓢。 她就那樣靜靜地躺著,像睡著了一般句灌。 火紅的嫁衣襯著肌膚如雪夷陋。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天胰锌,我揣著相機與錄音骗绕,去河邊找鬼。 笑死资昧,一個胖子當著我的面吹牛酬土,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播格带,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼撤缴,長吁一口氣:“原來是場噩夢啊……” “哼刹枉!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起屈呕,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤微宝,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后虎眨,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蟋软,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年嗽桩,在試婚紗的時候發(fā)現(xiàn)自己被綠了岳守。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡碌冶,死狀恐怖湿痢,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扑庞,我是刑警寧澤蒙袍,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站嫩挤,受9級特大地震影響害幅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岂昭,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一以现、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧约啊,春花似錦邑遏、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至外傅,卻和暖如春纪吮,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背萎胰。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工碾盟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人技竟。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓冰肴,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子熙尉,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容