還先說說C語言的內(nèi)存分配
1.棧區(qū)(stack):自動分配幢踏,釋放內(nèi)存线衫,靜態(tài)內(nèi)存,就存于棧區(qū)
windows下惑折,棧內(nèi)存分配2M授账,超出了限制,會提示stack overflow的錯誤
2.堆區(qū)(heap):由開發(fā)人員分配釋放惨驶,大概可以占用操作系統(tǒng)的80%
3.全局區(qū)或靜態(tài)區(qū)
4.字符常量區(qū)
5.程序代碼區(qū)
先來看一個靜態(tài)分配的例子:
void main(){
? ? int a[1024*1024*10] ;
? ? system("pause");
}?
這就是一個內(nèi)存溢出的例子白热。我們通常聲明一個變量,常規(guī)的寫法粗卜,都是靜態(tài)分配屋确。 上面說了,這樣分配续扔,是自動管理內(nèi)存攻臀。且在是棧內(nèi)存上。有上限纱昧,是2M刨啸。 ?而上述的寫法,達(dá)到了40M识脆,因?yàn)閕nt型為4字節(jié)设联。故這里就會報(bào)溢出善已。
再來看一個動態(tà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]);
}
free(p);
system("pause");
}
關(guān)鍵代碼:int* p = malloc(len * sizeof(int));
這里的malloc,就是分配動態(tài)內(nèi)存的代碼,這個方法的返回值是 void* 离例,就是說换团,可以是任意類型的指針! 這個指針宫蛆,指向的就是malloc生成的一塊內(nèi)存區(qū)域地址K野!R痢O牖ⅰ!例子中袍冷,實(shí)際上,是給一個int數(shù)組分本動態(tài)內(nèi)存猫牡。? 那么其指針p胡诗,其實(shí)就是第一個元素的地址而以,詳情指針那節(jié)的內(nèi)容淌友。當(dāng)使用完后煌恢,要手動釋放內(nèi)存 free(p);
那這個動態(tài)內(nèi)存,能不能動態(tài)增加呀--當(dāng)然是可以的
接上面的代碼:
int* p2 = realloc(p, sizeof(int) * (len + addLen));
可以看出震庭,realloc就是增加一塊內(nèi)存的大泄宓帧!第一個參數(shù)器联,就是動態(tài)內(nèi)存的指針二汛, 第二個參數(shù),就是增加后的總大胁ν亍肴颊!
那新的這一塊內(nèi)存的內(nèi)存地址,和舊的有沒有地址相比渣磷,有沒有改變婿着?
就是說,p2和p的值醋界,是否相等竟宋。
答案是,可能等形纺,也可能不等丘侠。
如果重新分配后,是縮小逐样,則肯定是同一塊
若是擴(kuò)大婉陷,就不一定了帚称。就要看原來的內(nèi)存區(qū)域,擴(kuò)大后的線性空間有沒有被占用秽澳,若被占用闯睹,則會重新開辟內(nèi)存,則P2和P就不同担神! 若沒被占用楼吃,則是同一塊!
還有可能妄讯,沒有已經(jīng)內(nèi)存可被擴(kuò)大了孩锡!則返回NULL。原指針依然有效
因此亥贸,可以先判斷 if(p2!=null){free(p2)}
除了malloc外躬窜,還有一種寫法
int *p=calloc(len, sizeof(len));
唯一的區(qū)別就是, calloc的兩個參數(shù)比malloc的更直觀炕置,更容易懂荣挨,其它都沒差。就是callo定義了單位大小朴摊,且有多少單位默垄! 不像malloc要自已去計(jì)算。
內(nèi)存分配的幾個注意事項(xiàng)
1.不能多次釋放
2.釋放完成后甚纲,給指針置NULL口锭,標(biāo)志已經(jīng)釋放內(nèi)存
3內(nèi)存泄漏(P重新賦值之后,再free介杆,并沒有真正釋放內(nèi)存)
第1點(diǎn)好理解鹃操,第2點(diǎn)的例子
if (p != NULL){
? ?free(p);
? ?p = NULL;
}
就是這樣操作,因?yàn)榭赡苡泻芏嗟胤酱荷冢紩扰袛?p是否為NULL组民,以免第1條悲劇的發(fā)生。
第3條的例子
int* p = malloc(2 * sizeof(int));
p = malloc(5 * sizeof(int));
free(p);
這就是內(nèi)存泄漏悲靴,因?yàn)樵俅钨x值時(shí)臭胜,返回的p,與第一個p癞尚,不是同一個了耸三! 這樣就相當(dāng)于,釋放了第2個p浇揩,第一個p就泄漏了仪壮!
正確的寫法是
int* p = malloc(2 * sizeof(int));
free(p);
p = malloc(5 * sizeof(int));
free(p);
就是說,在重新賦值前胳徽,就要先釋放一次积锅!
動態(tài)擴(kuò)爽彤,用realloc就不存在這個問題。