iOS知識總結(jié)(二):堆棧以及內(nèi)存分配

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

  • 棧(stack)

    由編譯器自動(dòng)分配釋放,無需手工管理挠蛉;
    存放函數(shù)的參數(shù)值、局部變量等肄满;
    操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧谴古,后入先出;
    棧區(qū)地址從高到低分配稠歉,是一塊連續(xù)的內(nèi)存區(qū)域掰担,棧頂?shù)刂泛腿萘渴窍到y(tǒng)預(yù)先規(guī)定好的,因此能獲得的棧的空間較小怒炸。

  • 堆(heap)

    用于動(dòng)態(tài)內(nèi)存分配带饱;
    由程序員分配釋放,若程序員不釋放阅羹,則可能造成內(nèi)存泄露纠炮,程序 結(jié)束時(shí)有可能由OS回收;
    堆是向高地址擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)灯蝴,是不連續(xù)的內(nèi)存區(qū)域,這是由于系統(tǒng)是用鏈表來存儲(chǔ)空閑內(nèi)存地址的孝宗,自然是不連續(xù)的穷躁,而鏈表的遍歷方向是由低到高地址的。堆的大小受制于計(jì)算機(jī)中的有效虛擬內(nèi)存因妇,所以堆獲得的空間比較大且靈活问潭。

  • 全局區(qū)/靜態(tài)區(qū)(Data Segment)

    全局變量和靜態(tài)變量在內(nèi)存中是放在一起的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域婚被,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域狡忙;
    該塊內(nèi)存在程序編譯的時(shí)候就已經(jīng)分配好了,在整個(gè)程序運(yùn)行期間始終不變址芯,程序結(jié)束后由系統(tǒng)釋放灾茁。

  • 常量區(qū)

    存放常量,不允許修改谷炸,常量字符串存放在這里北专,程序結(jié)束后由系統(tǒng)釋放。

  • 代碼區(qū)(text segment)

    存放函數(shù)體的二進(jìn)制代碼

整個(gè)內(nèi)存區(qū)域由高地址到低地址如下圖所示:


1156719-1d0de5ca1edc35af.png

堆和棧的區(qū)別

  1. 管理方式不同
    棧是由編譯器自動(dòng)管理旬陡,無需程序員手工控制拓颓;堆空間的申請和釋放是由程序員控制的,容易產(chǎn)生內(nèi)存泄露描孟。

  2. 空間大小不同
    棧是由高向低擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)驶睦,是一塊連續(xù)的區(qū)域砰左。棧頂?shù)牡刂泛蜅5淖畲笕萘渴怯上到y(tǒng)預(yù)先設(shè)定好的,當(dāng)申請的空間超過棧的剩余空間的時(shí)候场航,就提示溢出缠导,所以棧的空間較小。

    堆是由低向高擴(kuò)展的數(shù)據(jù)結(jié)構(gòu)旗闽,是不連續(xù)的內(nèi)存區(qū)域酬核。堆的大小受制于計(jì)算機(jī)中的有效虛擬內(nèi)存,所以堆獲得的空間比較大且靈活适室。

  3. 是否產(chǎn)生碎片
    對于堆來講嫡意,頻繁的創(chuàng)建銷毀勢必會(huì)造成內(nèi)存空間的不連續(xù),從而產(chǎn)生大量的碎片捣辆,使程序效率降低蔬螟。而棧則沒有這個(gè)問題,因?yàn)闂J窍冗M(jìn)后出的隊(duì)列汽畴,他們是如此的一一對應(yīng)旧巾,以至于永遠(yuǎn)都不可能有一個(gè)內(nèi)存塊從棧中彈出。

  4. 增長方向不同
    棧的增長方向是向下的忍些,是向著內(nèi)存地址減小的方向鲁猩;而堆則相反。

  5. 分配方式不同
    堆都是動(dòng)態(tài)分配的罢坝,沒有靜態(tài)分配的堆廓握。棧有兩種分配方式:靜態(tài)分配和動(dòng)態(tài)分配。靜態(tài)分配是編譯器完成的嘁酿,比如局部變量的分配隙券。動(dòng)態(tài)分配是有alloc函數(shù)進(jìn)行分配的,但是棧的動(dòng)態(tài)分配和堆是不同的闹司,他的動(dòng)態(tài)分配由編譯器進(jìn)行釋放娱仔,無需我們手工實(shí)現(xiàn)。 棧的分配釋放是由編譯器完成的游桩,棧也有動(dòng)態(tài)分配牲迫,但其和堆是不同的,無需手工實(shí)現(xiàn)借卧;而堆是動(dòng)態(tài)分配的恩溅。

  6. 分配效率不同
    棧是機(jī)器系統(tǒng)提供的數(shù)據(jù)結(jié)構(gòu),計(jì)算機(jī)會(huì)在底層對棧提供支持:分配專門的寄存器存放棧的地址谓娃,壓棧出棧都有專門的指令執(zhí)行脚乡。
    而堆的機(jī)制復(fù)雜的多,例如為了分配一塊內(nèi)存,庫函數(shù)會(huì)按照一定的算法(具體的算法可以參考數(shù)據(jù)結(jié)構(gòu)/操作系統(tǒng))在堆內(nèi)存中搜索可用的足夠大的空間奶稠,如果沒有足夠大的空間(可能是由于內(nèi)存碎片太多)俯艰,就有需要操作系統(tǒng)來重新整理內(nèi)存空間,這樣就有機(jī)會(huì)分到足夠大小的內(nèi)存锌订,然后返回竹握。顯然,堆的效率比棧要低得多辆飘。

其他

之所以分成這么多個(gè)區(qū)域啦辐,主要基于以下考慮:

一個(gè)進(jìn)程在運(yùn)行過程中,代碼是根據(jù)流程依次執(zhí)行的蜈项,只需要訪問一次芹关,當(dāng)然跳轉(zhuǎn)和遞歸有可能使代碼執(zhí)行多次,而數(shù)據(jù)一般都需要訪問多次紧卒,因此單獨(dú)開辟空間以方便訪問和節(jié)約空間侥衬。

臨時(shí)數(shù)據(jù)及需要再次使用的代碼在運(yùn)行時(shí)放入棧區(qū)中,生命周期短跑芳。

全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)有可能在整個(gè)程序執(zhí)行過程中都需要訪問轴总,因此單獨(dú)存儲(chǔ)管理。

堆區(qū)由用戶自由分配博个,以便管理怀樟。

//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ū)罪塔,編譯器可能會(huì)將它與p3所指向的"123456"優(yōu)化成一個(gè)地方。 
}

棧是一個(gè)用來存儲(chǔ)局部和臨時(shí)變量的存儲(chǔ)空間养葵。在現(xiàn)代操作系統(tǒng)中,一個(gè)線程會(huì)分配一個(gè)棧. 當(dāng)一個(gè)函數(shù)被調(diào)用,一個(gè)stack frame(棧幀)就會(huì)被壓到stack里征堪。里面包含這個(gè)函數(shù)涉及的參數(shù),局部變量,返回地址等相關(guān)信息。當(dāng)函數(shù)返回后,這個(gè)棧幀就會(huì)被銷毀关拒。而這一切都是自動(dòng)的,由系統(tǒng)幫我們進(jìn)行分配與銷毀佃蚜。對于程序員來說,我們無須自己調(diào)度着绊。

在objective-c中只支持一個(gè)類型對象:blocks谐算。
關(guān)于在block中的對象的生命周期問題。出現(xiàn)這問題的原因是归露,block是新的對象洲脂,當(dāng)你使用block時(shí)候,如果你想對其保持引用剧包,你需要對其進(jìn)行copy操作恐锦,(從棧上copy到堆中往果,并返回一個(gè)指向他的指針),而不是對其進(jìn)行retain操作

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末一铅,一起剝皮案震驚了整個(gè)濱河市陕贮,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌潘飘,老刑警劉巖肮之,帶你破解...
    沈念sama閱讀 217,185評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異卜录,居然都是意外死亡戈擒,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評論 3 393
  • 文/潘曉璐 我一進(jìn)店門暴凑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來峦甩,“玉大人,你說我怎么就攤上這事现喳】粒” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評論 0 353
  • 文/不壞的土叔 我叫張陵嗦篱,是天一觀的道長冰单。 經(jīng)常有香客問我,道長灸促,這世上最難降的妖魔是什么诫欠? 我笑而不...
    開封第一講書人閱讀 58,339評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上茵宪,老公的妹妹穿的比我還像新娘荤崇。我一直安慰自己,他們只是感情好被廓,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著萝玷,像睡著了一般嫁乘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上球碉,一...
    開封第一講書人閱讀 51,287評論 1 301
  • 那天蜓斧,我揣著相機(jī)與錄音,去河邊找鬼睁冬。 笑死挎春,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播搂蜓,決...
    沈念sama閱讀 40,130評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狼荞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了帮碰?” 一聲冷哼從身側(cè)響起相味,我...
    開封第一講書人閱讀 38,985評論 0 275
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎殉挽,沒想到半個(gè)月后丰涉,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡斯碌,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評論 3 334
  • 正文 我和宋清朗相戀三年一死,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片傻唾。...
    茶點(diǎn)故事閱讀 39,779評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡投慈,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出冠骄,到底是詐尸還是另有隱情伪煤,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評論 5 345
  • 正文 年R本政府宣布凛辣,位于F島的核電站抱既,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏扁誓。R本人自食惡果不足惜防泵,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蝗敢。 院中可真熱鬧捷泞,春花似錦、人聲如沸寿谴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽拭卿。三九已至骡湖,卻和暖如春贱纠,著一層夾襖步出監(jiān)牢的瞬間峻厚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評論 1 269
  • 我被黑心中介騙來泰國打工谆焊, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留惠桃,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像辜王,于是被迫代替她去往敵國和親劈狐。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評論 2 354