iOS程序所占的內(nèi)存分區(qū)
-
棧區(qū):
- 存放函數(shù)的參數(shù)值,局部變量的值,基本數(shù)據(jù)類型等
- 由編譯器自動分配釋放,不需要程序猿管理棧內(nèi)存
- 存放的數(shù)據(jù)變量遵循先進后出,且棧地址是從高到低分配
-
堆區(qū):
- OC中用alloc函數(shù)生成的對象都是放在堆區(qū)
- 堆區(qū)的內(nèi)存一般由程序猿進行釋放,如果不釋放,程序運行結(jié)束后由系統(tǒng)進行回收
- 堆區(qū)存放數(shù)據(jù)遵循先進先出,地址是從低到高
-
全局區(qū)/靜態(tài)區(qū)(static):
- 全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,
未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域, - 程序結(jié)束后由系統(tǒng)進行釋放
- eg:int a;未初始化的。int a = 10;已初始化的
- 全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,
-
常量區(qū):
- 常量字符串就是放在這里的。 程序結(jié)束后由系統(tǒng)釋放
-
代碼區(qū):
- 存放函數(shù)體的二進制代碼
代碼示例講述
這是一個前輩寫的,非常詳細
//main.cpp
int a = 0; 全局初始化區(qū)
char *p1; 全局未初始化區(qū)
main()
{
int b; 棧
char s[] = "abc"; 棧
char *p2; 棧
char *p3 = "123456"; 123456\0在常量區(qū),p3在棧上。
static int c =0; 全局(靜態(tài))初始化區(qū)
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
分配得來得10和20字節(jié)的區(qū)域就在堆區(qū)。
strcpy(p1, "123456"); 123456\0放在常量區(qū)。
}
如下圖所示:代碼區(qū)存放于低地址,棧區(qū)存放于高地址,且區(qū)與區(qū)之間并不是連續(xù)的

image
注意事項:
- 在iOS中,堆區(qū)的內(nèi)存是應用程序共享的,而堆區(qū)的內(nèi)存分配是由系統(tǒng)負責的
- 當一個app啟動后,代碼區(qū),常量區(qū),全局區(qū)大小已固定,因此指向這些區(qū)的指針不會產(chǎn)
生崩潰性的錯誤。而堆區(qū)和棧區(qū)是時時刻刻變化的(堆的創(chuàng)建銷毀,棧的彈入彈出),所
以當使用一個指針指向這兩個區(qū)里面的內(nèi)存時,一定要注意內(nèi)存是否已經(jīng)被釋放,否則會
產(chǎn)生程序崩潰(也即是野指針報錯)
堆區(qū)和棧區(qū)的比較
1.按照管理方式:
- 棧:系統(tǒng)編譯器管理,不需要程序猿管理
- 堆:釋放工作由程序員手動管理,不及時回收容易產(chǎn)生內(nèi)存泄露
2.按照分配方式:
- 棧:靜態(tài)分配和動態(tài)分配
- 靜態(tài)分配:靜態(tài)分配是系統(tǒng)編譯器完成的,比如局部變量的分配
- 動態(tài)分配:動態(tài)分配是有alloc函數(shù)進行分配的,但是棧的動態(tài)分配和堆是不同的,它
的動態(tài)分配也由系統(tǒng)編譯進行釋放,不需要程序員手動管理
- 堆:堆是動態(tài)分配和回收內(nèi)存的,沒有靜態(tài)分配的堆
堆區(qū)的一個例子
創(chuàng)建一個新的對象時,對象p指針存放在棧區(qū),p將指向在堆區(qū)開辟的一塊存儲空間Person
image
在程序結(jié)束之前,p對象必須release,不然系統(tǒng)不知道釋放堆區(qū)的Person內(nèi)存。
如果p對象沒有release,只是p=nil; 就是p指針指向了堆區(qū)地址為0的地方,那么原來的Person永遠無法再次訪問,而且也無法釋放掉。
堆是所有程序共享的內(nèi)存,當N個這樣的內(nèi)存得不到釋放,堆區(qū)會被擠爆,程序立馬癱瘓。這就是內(nèi)存泄漏。
參考①:http://www.cnblogs.com/hangdada/p/4982989.html