內(nèi)存總體被分為四大區(qū)域:堆區(qū)、棧區(qū)捌显、全局區(qū)茁彭、代碼區(qū)。每個區(qū)所存放的內(nèi)容以及內(nèi)容的聲明周期不同扶歪。將內(nèi)存進行區(qū)域劃分有利于內(nèi)存管理理肺,從而提高對數(shù)據(jù)的處理效率。
A. 全局區(qū)
全局區(qū)也稱為靜態(tài)區(qū),存放全局變量和靜態(tài)變量,其中初始化的全局變量和靜態(tài)變量存放在同一區(qū)塊说墨,未初始化的全局變量和靜態(tài)變量存放在相鄰的區(qū)塊胖笛,程序結(jié)束后,由系統(tǒng)自動釋放画切。
1. 樣例分析
char * getStr1() {
char *fp1 = "abcd";
return fp1;
};
char * getStr2() {
char *fp2 = "abcd";
return fp2;
}
int main() {
char *p = getStr1();
char *q = getStr2();
printf("p:%s, p:%p\n", p, p);
printf("q:%s, q:%p\n", q, q);
return 0;
}
2. 打印結(jié)果
p:abcd, p:0x100b68f8e
q:abcd, q:0x100b68f8e
3. 內(nèi)存分配圖
4. 分析:
1竣稽、進入main
函數(shù)
2、在棧中創(chuàng)建char *
變量p
3霍弹、進入getStr1
方法
4毫别、在棧中創(chuàng)建char *
變量fp1
5、字符串abcd
屬于靜態(tài)變量典格,存儲在全局區(qū)岛宦,且由系統(tǒng)進行釋放。通過打印得知其地址值為0x100b68f8e
6耍缴、將字符串的地址賦值給指針變量fp1
砾肺,那么變量fp1
則指向字符串所在的內(nèi)存
7、返回fp1
的指針防嗡,并將該指針賦值給變量p
变汪,getStr1
方法結(jié)束,fp1
變量銷毀蚁趁,變量p
指向字符串的所在的內(nèi)存
8裙盾、創(chuàng)建并賦值變量q
的方式同于步驟2
至步驟7
因此最后打印的結(jié)果是變量p
內(nèi)存存放的值與q
相同,p
指向的地址值也與q
相同他嫡。
B. 棧區(qū):
棧區(qū)由編譯器自動分配釋放局部變量和函數(shù)參數(shù)的值番官。
1. 樣例分析
char * getStr3() {
char str[] = "abcd";
return str;
};
int main() {
char *strp = getStr3();
printf("strp:%s, strp:%p", strp, strp);
return 0;
}
2. 打印結(jié)果
strp:?M?y??7????, strp:0x7ffee691376b
3. 繪制內(nèi)存圖
4. 分析:
1、進入main
函數(shù)
2钢属、棧中創(chuàng)建strp
變量
3徘熔、進入getStr3
函數(shù)
4、棧中創(chuàng)建str
變量
5署咽、全局區(qū)存入字符串abcd
6近顷、將全局區(qū)的字符串復(fù)制一份賦值給str
變量
7生音、返回str
變量的地址,getStr3
函數(shù)運行結(jié)束窒升,str
變量釋放缀遍,將str
的地址值賦值給變量strp
,strp
指向str
的內(nèi)存
8饱须、因str
的內(nèi)存已經(jīng)被釋放域醇,所以str
內(nèi)存中的內(nèi)容未知,故而亂碼
C. 堆區(qū)分析
堆區(qū)由程序員手動創(chuàng)建和釋放蓉媳,若程序員未釋放對應(yīng)的變量譬挚,那么在程序結(jié)束后可能會被系統(tǒng)釋放。
1. 樣例分析
char * getStr4() {
char *str = (char *)malloc(100);
printf("str: %p\n", str);
if (str == NULL) {
return NULL;
}
strcpy(str, "abcd");
return str;
}
int main() {
char *strp1 = getStr4();
if (strp1 != NULL) {
printf("strp1:%s, strp1:%p\n", strp1, strp1);
free(strp1);
strp1 = NULL;
}
return 0;
}
2. 打印結(jié)果:
str: 0x7fd490c02a70
strp1:abcd, strp1:0x7fd490c02a70
3. 內(nèi)存圖繪制
4. 分析
1酪呻、進入main
函數(shù)
2减宣、棧區(qū)創(chuàng)建strp1
變量
3、進入getStr4
函數(shù)
4玩荠、棧區(qū)創(chuàng)建str
變量
5漆腌、堆區(qū)分配內(nèi)存,并將分配好的內(nèi)存地址賦值給str
變量阶冈,str
指向分配好的堆內(nèi)存
6闷尿、全局區(qū)分配字符串abcd
的內(nèi)存,并將其值復(fù)制一份賦值給堆中分配的內(nèi)存
7女坑、返回str
變量的值填具,getStr4
函數(shù)結(jié)束,str
變量釋放匆骗,并將值賦值給strp1
劳景,strp1
指向堆中分配的內(nèi)存
8、打印結(jié)束后绰筛,釋放堆中的內(nèi)存
D. 棧的生長方向和內(nèi)存存放方向
棧的生長方向:高字節(jié) -> 低字節(jié)
堆的生長方向:低字節(jié) -> 高字節(jié)
內(nèi)存的存放方向: 低字節(jié) -> 高字節(jié)