在編程中,內(nèi)存分為五大分區(qū):棧區(qū)內(nèi)存,堆區(qū),靜態(tài)區(qū),常量區(qū),代碼區(qū).
看下面一個(gè)函數(shù),你能發(fā)現(xiàn)它又什么問題?又該如何改正?
char * getString() {
char str[20] = "iPhone";
return str;
}
首先,我們先來了解下五大分區(qū)的作用,然后上面的getString()函數(shù)的錯(cuò)誤,就迎刃而解了.
棧區(qū)內(nèi)存:是給函數(shù)里面的局部變量和形參分配內(nèi)存.當(dāng)發(fā)生函數(shù)調(diào)用時(shí),操作系統(tǒng)就會(huì)為這個(gè)函數(shù)里面的所有局部變量和形參分配內(nèi)存, 當(dāng)函數(shù)調(diào)用完畢時(shí), 所有為這個(gè)函數(shù)分配的棧區(qū)內(nèi)存就會(huì)被系統(tǒng)回收.
堆區(qū):由程序員自己負(fù)責(zé)分配和釋放. 有分配就得有釋放, 否則會(huì)導(dǎo)致內(nèi)存泄露
靜態(tài)區(qū):用static修飾的變量和全局變量會(huì)被分配在靜態(tài)區(qū),靜態(tài)區(qū)內(nèi)存由操作系統(tǒng)負(fù)責(zé)分配和釋放(并且使用static修飾的變量只會(huì)被初始化一次)
常量區(qū):代碼里寫的數(shù)值常量,字符串常量,都是存儲在常量區(qū)的,常量區(qū)的內(nèi)存也是操作系統(tǒng)負(fù)責(zé)分配和釋放.常量區(qū)的最大特點(diǎn)是內(nèi)容不可修改.
我們已經(jīng)了解了五大分區(qū)每個(gè)分區(qū)的特性,那么接下來,我們來分析一下getString()函數(shù)錯(cuò)在哪里?
在getString函數(shù)中:char str[20]= "iPhone";定義了一個(gè)長度為20的字符數(shù)組,因?yàn)槭呛瘮?shù)里面的局部變量,因此它的內(nèi)存是在棧區(qū)存放,也就是說,現(xiàn)在棧區(qū)里面申請了一塊內(nèi)存區(qū)域用來存放getString函數(shù)里面的局部變量,"iPhone"這個(gè)字符數(shù)組也就保存在了這個(gè)棧區(qū)內(nèi)存.
接下來return str;返回?cái)?shù)組的地址.函數(shù)調(diào)用結(jié)束后,系統(tǒng)將會(huì)對棧區(qū)的getString的內(nèi)存進(jìn)行回收.也就是說,返回的str這個(gè)指針指向數(shù)組已經(jīng)不存在了.那么我們該如何改進(jìn)才能拿到這個(gè)"iPhone"字符數(shù)組呢?
這就需要利用堆區(qū)的特性來進(jìn)行改進(jìn).改進(jìn)后函數(shù)如下:
char * getString() {
???????? char * str = malloc(10) ;//動(dòng)態(tài)申請一個(gè)堆區(qū)內(nèi)存,來存儲字符
???????? strcpy(str , "iPhone");//把常量區(qū)的"iPhone"字符拷貝到堆區(qū)的內(nèi)存中
????????? return str;//返回的是堆區(qū)的地址
}
通過這樣改進(jìn)后我們就能拿到一個(gè)指向堆區(qū)的指針.(調(diào)用過這個(gè)函數(shù)后,要記得釋放free(); )
char * getString() {
char str[20] = "iPhone";
return str;
}