在iOS中酬土,虛擬內(nèi)存主要分為棧區(qū)
、堆區(qū)
啃擦、全局(靜態(tài))區(qū)
囊蓝、常量區(qū)
、代碼區(qū)
令蛉,其中全局(靜態(tài))區(qū)
又分為BSS區(qū)
和數(shù)據(jù)區(qū)
聚霜。如下圖所示:
棧區(qū)(Stack)
棧區(qū)由編譯器自動分配和釋放,是一塊連續(xù)的內(nèi)存區(qū)域珠叔,主要用于存放局部變量
和函數(shù)的參數(shù)(id self蝎宇,SEL _cmd)
。
特點
- 棧由
編譯器自動分配和釋放
祷安,是一塊連續(xù)的內(nèi)存區(qū)域姥芥。 - 棧內(nèi)部以
幀(Frame)
的結(jié)構(gòu)進(jìn)行入棧和出棧,遵循先進(jìn)后出(FILO)
原則汇鞭。 - 棧是
從高地址向低地址擴展
的數(shù)據(jù)結(jié)構(gòu)凉唐,地址空間在iOS中以Ox7
開頭。 - 棧
在運行時分配
霍骄。
優(yōu)缺點
- 優(yōu)點:因為棧是由編譯器自動分配和釋放台囱,所以不會產(chǎn)生內(nèi)存碎片,且快速高效读整。
- 缺點:內(nèi)存大小有限制玄坦,在iOS中,主線程中棧的大小為
1MB
,子線程中棧的大小為512kb
煎楣,在MAC OS中棧的大小為8MB
豺总。(詳情可見官方文檔Threading Programming Guide)
棧幀(Frame)
棧區(qū)(stack)
內(nèi)存是以幀的結(jié)構(gòu)來管理的,每次執(zhí)行一個函數(shù)择懂,都會生成新的幀(Frame)
喻喳,所有的幀都按順序添加到棧中,最新生成的幀存放在最上面困曙。每次新生成一幀表伦,叫做入棧(push)
,每次釋放一幀慷丽,叫做出棧(pop)
蹦哼,當(dāng)所有的幀都被釋放掉,整個棧也會被釋放要糊。整個過程如下圖所示:
我們通過下面的實例來具體分析:
int main() {
int a = 10;
int b = 20;
return test(a, b);
}
- 當(dāng)執(zhí)行
main()
函數(shù)時纲熏,系統(tǒng)生成對應(yīng)的幀并入棧,main()
函數(shù)里的局部變量a
和b
都存放在這個幀中锄俄。 - 當(dāng)執(zhí)行到
test()
函數(shù)時局劲,系統(tǒng)又會生成對應(yīng)的幀并入棧,用來保存test()
函數(shù)內(nèi)部的局部變量奶赠,這個新幀會疊加在最上面鱼填。 - 執(zhí)行完
test()
函數(shù)后,對應(yīng)的幀被釋放毅戈,里面存放的局部變量都會被銷毀苹丸。 - 執(zhí)行完
main()
函數(shù)后,對應(yīng)的幀被釋放苇经,此時所有的幀都被釋放谈跛,整個棧區(qū)(stack)
也會被釋放。
堆區(qū)(Heap)
堆區(qū)由程序員分配和釋放的塑陵,也可由垃圾回收機制釋放感憾,是一塊不連續(xù)的內(nèi)存空間。主要存放:OC
中使用alloc
或者new
創(chuàng)建的對象令花,C
語言中使用malloc
阻桅、calloc
、realloc
分配的空間(C
中這些需要使用free
來釋放)兼都。
特點
- 堆由
程序員分配和釋放
嫂沉,是一塊不連續(xù)的內(nèi)存空間。 - 堆是類似于
鏈表結(jié)構(gòu)
(便于增刪扮碧,不便于查詢)趟章,遵循先進(jìn)先出(FIFO)
原則杏糙。 - 堆是
從低地址向高地址拓展
的數(shù)據(jù)結(jié)構(gòu),地址空間在iOS中以0x6
開頭蚓土。 - 堆
在運行時分配
宏侍。
優(yōu)缺點
- 優(yōu)點:由于內(nèi)存空間不連續(xù),因此使用靈活方便蜀漆,隨取隨用谅河。
- 缺點:需要手動管理內(nèi)存,速度慢确丢,且容易產(chǎn)生內(nèi)存碎片绷耍。
堆區(qū)對象的內(nèi)存訪問
Person *p = [Person alloc] init];
這個案例中,實例化的Person
對象鲜侥,存在于堆區(qū)褂始,指針變量p
存放于棧區(qū),p
的內(nèi)存空間存放Person
對象的地址描函。所以崎苗,若要訪問Person
對象,需要先訪問棧區(qū)的指針變量p
赘阀,再通過p
存放的地址來訪問Person
對象益缠。
全局(靜態(tài))區(qū)
全局區(qū)是編譯期分配
的內(nèi)存空間脑奠,由系統(tǒng)管理基公,在程序啟動時由分配,程序結(jié)束時釋放宋欺,內(nèi)存空間一般以0x1
開頭轰豆。在程序運行過程中,此內(nèi)存中的數(shù)據(jù)一直存在齿诞。其又分為兩部分區(qū)域:
-
BSS區(qū)(.bss)
:存放未初始化的全局變量
和靜態(tài)變量
酸休。 -
數(shù)據(jù)區(qū)(.data)
:存放已初始化的全局變量
和靜態(tài)變量
。
全局變量是指在運行中值可以被動態(tài)修改的變量祷杈。
靜態(tài)變量是指由static
修飾的變量斑司,值不能被修改,包含全局靜態(tài)變量和局部靜態(tài)變量但汞。
常量區(qū)(.rodata)
常量區(qū)是編譯時分配
的內(nèi)存空間宿刮,由系統(tǒng)管理,在程序啟動時分配私蕾,在程序結(jié)束后釋放僵缺,主要存放常量
,不允許被修改踩叭,內(nèi)存空間一般以0x1
開頭磕潮。
代碼區(qū)(.text)
代碼區(qū)是在編譯期分配
翠胰,用來存放函數(shù)被編譯后的二進(jìn)制代碼
。代碼段只允許讀操作自脯,不允許寫操作之景。