iOS 內(nèi)存概述

在iOS中內(nèi)存分為五大區(qū)域:棧去、堆區(qū)、全局區(qū)、常量區(qū)、代碼區(qū)

內(nèi)存分區(qū)

棧區(qū)(Stack)

  • 高地址向低地址擴(kuò)展的系統(tǒng)數(shù)據(jù)結(jié)構(gòu),對(duì)應(yīng)的進(jìn)程或者線程是唯一的
  • 是一塊連續(xù)的內(nèi)存區(qū)域,遵循先進(jìn)后出(FILO)原則
  • 運(yùn)行時(shí)分配,在iOS中以0x7開頭
  • 由編譯器自動(dòng)分配并釋放的,主要用來存儲(chǔ):局部變量、函數(shù)參數(shù)(如隱藏參數(shù)(id self, SEL _cmd))

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):因?yàn)闂J?code>編譯器自動(dòng)分配并釋放的,不會(huì)產(chǎn)生內(nèi)存碎片,快速且高效
  • 缺點(diǎn):棧的內(nèi)存大小有限制,數(shù)據(jù)不靈活
    • iOS主線程大小是1MB,其他線程是512KB
    • MAC上是8MB

堆區(qū)(Heap)

  • 堆是由低地址向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)
  • 不連續(xù)的內(nèi)存區(qū)域,類似鏈表結(jié)構(gòu)(便于增刪,不便于查找),遵循先進(jìn)先出(FOFI)原則
  • 運(yùn)行時(shí)分配的,在iOS中以0x6開頭
  • 程序員動(dòng)態(tài)分配和釋放的,如果程序員沒有釋放,在程序結(jié)束后由系統(tǒng)回收,主要用來存儲(chǔ):開辟空間創(chuàng)建對(duì)象
  • 訪問堆中內(nèi)存時(shí),一般需要通過對(duì)象讀取到棧區(qū)的指針地址,然后通過指針地址訪問堆區(qū)

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):靈活方便,適應(yīng)面廣泛
  • 缺點(diǎn):需要手動(dòng)管理,速度慢,容易產(chǎn)生內(nèi)存碎片

全局區(qū)\靜態(tài)區(qū)(.bss&.data)

  • 編譯時(shí)期分配的內(nèi)存空間,在程序運(yùn)行期間,數(shù)據(jù)一直存在,程序結(jié)束后系統(tǒng)釋放
  • 在iOS中一般以0x1開頭
  • 可讀可寫區(qū)域

主要用來存放:

  • 未初始化全局變量靜態(tài)變量,即BSS區(qū)
  • 已初始化全局變量靜態(tài)變量,即DATA區(qū)
    • 全局變量是指變量值可以在運(yùn)行時(shí)被動(dòng)態(tài)修改,而靜態(tài)變量static修飾的變量,包含靜態(tài)局部變量靜態(tài)全局變量

常量區(qū)(.rodata)

  • 編譯時(shí)期分配的內(nèi)存空間,程序結(jié)束后系統(tǒng)自動(dòng)釋放
  • 只讀區(qū)域
  • 主要存放:已經(jīng)使用且沒有指向的字符串常量
  • 字符串常量因?yàn)榭赡茉诔绦蛑?code>多次使用,所有在程序運(yùn)行前提前分配內(nèi)存

代碼區(qū)(.text)

  • 編譯時(shí)分配
  • 只讀區(qū)域
  • 主要存放:程序運(yùn)行的代碼,代碼會(huì)編譯成二進(jìn)制存到內(nèi)存

函數(shù)棧(棧幀)

  • 函數(shù)在運(yùn)行中且未完成時(shí)期占用的一塊獨(dú)立的連續(xù)內(nèi)存區(qū)域
  • 每一個(gè)線程都有專用的??臻g,該棧空間可以在線程期間自由使用,當(dāng)前線程的函數(shù)共享改棧空間,每一個(gè)函數(shù)使用的棧空間是一個(gè)棧幀,所有的棧幀組成了這個(gè)線程完整的棧
  • 函數(shù)的調(diào)用是發(fā)生在棧上,每一個(gè)函數(shù)的相關(guān)信息(局部變量,調(diào)用記錄等)都存儲(chǔ)在一個(gè)棧幀中,每執(zhí)行一次函數(shù)調(diào)用就會(huì)生成一個(gè)新的棧幀,然后將其壓入函數(shù)棧,當(dāng)函數(shù)執(zhí)行結(jié)束時(shí),則將函數(shù)對(duì)應(yīng)的棧幀出棧并釋放

堆棧溢出

一般情況下我們是不需要考慮堆棧的大小問題,但是堆棧不是無上限的,過多的遞歸會(huì)導(dǎo)致棧溢出,過多的alloc會(huì)導(dǎo)致堆溢出

預(yù)付堆棧溢出的方法:

  • 避免層次過深得遞歸調(diào)用
  • 不要使用過多的局部變量,控制局部變量大小
  • 避免占用大內(nèi)存的對(duì)象的分配,及時(shí)釋放
  • 在適當(dāng)情況下調(diào)用系統(tǒng)API修改線程的堆棧大小
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 版權(quán)聲明作者:zuoxiaolong(左瀟龍)出處:博客園左瀟龍的技術(shù)博客--http://www.cnblogs...
    端木軒閱讀 317評(píng)論 0 0
  • 在iOS中,內(nèi)存主要分為 棧區(qū)、堆區(qū)、全局區(qū)、常量區(qū)、代碼區(qū) 五大區(qū)域。如下圖所示 下面分別介紹這五大區(qū) 棧區(qū)(S...
    恍然如夢(mèng)_b700閱讀 753評(píng)論 0 2
  • 寫在前面 基本問題: 介紹下 Java 內(nèi)存區(qū)域(運(yùn)行時(shí)數(shù)據(jù)區(qū))。JDK7 和 JDK8 在內(nèi)存結(jié)構(gòu)上有什么變化 ...
    Shaw_Lee閱讀 200評(píng)論 0 0
  • 本節(jié)將會(huì)介紹一下JVM的內(nèi)存結(jié)構(gòu),JVM運(yùn)行時(shí)數(shù)據(jù)區(qū)的各個(gè)組成部分:堆,方法區(qū),程序計(jì)數(shù)器,Java虛擬機(jī)棧,本地...
    keyuan0214閱讀 289評(píng)論 0 0
  • 在iOS中,內(nèi)存主要分為棧區(qū)、堆區(qū)、全局區(qū)、常量區(qū)、代碼區(qū)五大區(qū)域。如下圖所示 下面分別介紹這五大區(qū) 棧區(qū)(Sta...
    輝輝歲月閱讀 1,047評(píng)論 0 1

友情鏈接更多精彩內(nèi)容