新聞中心
說起內存管理,看似老生常談,而真正掌握內存管理的核心其實并不簡單。ARC/MRR以及“誰分配誰就負責釋放”這種基本原則是很重要的,但不是本 文要討論的重點。之前本人還沒在小站發(fā)過相關的文章,本篇文章中,我本人是想結合實際開發(fā)和調試中遇到的一些細節(jié)問題,來談談iOS的內存管理內在機制和 調試方法。

成都創(chuàng)新互聯(lián)公司主營休寧縣網(wǎng)站建設的網(wǎng)絡公司,主營網(wǎng)站建設方案,app軟件定制開發(fā),休寧縣h5重慶小程序開發(fā)公司搭建,休寧縣網(wǎng)站營銷推廣歡迎休寧縣等地區(qū)企業(yè)咨詢
上一篇文章已經是4月份的了,時間飛快又過去了好久,小站5月份沒有文章更新,罪過罪過。最近小站的站長我又轉換到新團 隊新崗位,在支付寶做客戶端開發(fā)感受頗多,不過身在一個技術流團隊,工作很有挑戰(zhàn),自己感覺很充實、很“幸福”。iOS開發(fā)當中的內存管理,可深可淺,一 般應用程序開發(fā)過程當中可能并不需要關注太多,如果不是來到支付寶,也許就不會有這么多心得來整理此文。
關于內存,我準備分為內存管理的基本原則、原理和調試方法、實際問題幾部分整理。那么接下來我就和大家一起復習和稍微深入一下iOS的內存管理的原理和原則。
0. 概述
內 存,簡單來說就是內部存儲,復雜來說要從馮·諾依曼計算機結構說起。馮·諾依曼結構,也稱做普林斯頓結構,目前和哈佛結構相對,指出了計算機由運算器、控 制器、存儲器、輸入和輸出設備幾大部件組成。如今我們個人用的機器估計都是這個套路,而且運算器和控制器都合在一起,就是CPU,中央處理器。那么內存就 是CPU能直接讀寫訪問數(shù)據(jù)的地方(寄存器是在CPU內的,不算哈),有些朋友說誰誰誰的iPhone內存16G、64G,我只能說這個理解方法僅限于存 儲部件放在手機里(內)了,嚴格來講這算“外存”,我們要討論的不是這個。
馮·諾依曼結構還說了,內存是用來存啥的呢?指令+數(shù)據(jù)?。ü鸬目峙戮筒灰粯恿耍τ谖覀冮_發(fā)者來說,指令基本就是代碼邏輯,至于數(shù)據(jù)么變量常量肯定都算是的了。
內存有多大?不大,現(xiàn)今主流的個人機器也就幾G的樣子。iPhone? 統(tǒng)統(tǒng)1G。
我們操作系統(tǒng)都是運行在內存之上的,1G好像不算大,所以為了支持多進程,也為了支持大程序,抽象的虛擬存儲的概念誕生了。
簡要的概念先陳述到這,下面詳細說。哦,對了,ARC和MRR我還是得提一下,這個要是真不知道還真的自己先去了解一下去。
1. 通用內存基本原理
說iOS的內存,有必要先看看一般的計算機都是怎么干的,iPhone也是計算機,通用的道理一樣要遵循。這里提兩方面:虛存的概念,內存內容的大致分布。
虛 擬存儲系統(tǒng)。剛剛提到了,物理內存就那么大點,但是還要跑多個程序,還要接受消耗很大內存的程序,這怎么辦?涼拌。搞計算機的人都是很聰明的,在操作系統(tǒng) 層面做了物理地址和邏輯地址之間的映射轉換,當然處理器硬件上也做了支持。一個程序在運行時,實際要用到的指令和數(shù)據(jù)都是很有限的,不可能從頭到尾同時 用。那么對于一個程序來說,假裝自己有非常大的空間,實際上只要有條理的把暫時要用到的部分放進物理內存供CPU訪問就好,這樣第二個問題解決了。那既然 每個程序(進程)只用一小塊,那整個物理內存就可以分給多個程序(進程)用了,***個問題也迎刃而解。當然,這樣做的前提是,數(shù)據(jù)和指令的動態(tài)進出,用完 了的暫時不用的踢出內存,需要用的及時加載進來。這個具體的實現(xiàn)方式就多種多樣了,很多實現(xiàn)方式是在外存中開了個交換區(qū)供換入換出,但iOS可略有不同。
內 存的大致分布。不久以前,我發(fā)了一篇文章整理了Mach-O文件的格式分析,里面很復雜地放了好多東西,包括我們Build打包時的代碼和數(shù)據(jù)。而 Mach-O文件正是我們開發(fā)內容的一個靜態(tài)展現(xiàn)形式,要想在運行的時候看樣子,就得看這文件里包含的東西是怎么放進內存的。Objective-C是基 于C的,不放看下C程序進程的內存分布:
一個運行時進程的典型內存分布
最簡單來說分為兩大部分:指令+數(shù)據(jù)。再細分一點,五部分:代碼(指令),初始化數(shù)據(jù)區(qū),未初始化數(shù)據(jù)區(qū),堆,棧。代碼(指令,text)就不用說了,最靜態(tài)的,就是只讀的東西;
初始化數(shù)據(jù),簡單理解就是有初始值的變量、常量;
未初始化數(shù)據(jù),只聲明未給值的變量,運行前統(tǒng)統(tǒng)為0,之所以單獨分出來,估計是性能考慮,因為這些東西都是0,沒必要放在程序包里,也不用copy;
棧,程序運行記錄,每個線程,也就是每個執(zhí)行序列各有一個(看crash log最容易理解),都是編譯的時候能確定好的,還有一個特點就是這里面的數(shù)據(jù)可以不用指針,也不會丟;
堆, 最靈活的內存區(qū),用途多多,動態(tài)分配和釋放,編譯時不能提前確定,我們的Objective-C對象都是這么來的,都存在這里,通常堆中的對象都是以指針 來訪問的,指針從線程棧中來,但不獨屬于某個線程,堆也是對復雜的運行時處理的基礎支持,還有就是ARC還是MRR、“誰分配誰釋放”說的都是堆上對象的 管理;
其實,這個內存中的布局方式大部分操作系統(tǒng)中的大部分進程都是類似的。Objective-C的程序包對運行時有著復雜的支持和內容劃分,但也都是在這個大的框架下進行的。
2. iOS的內存管理
其實,iOS的內存管理和其它操作系統(tǒng)大同小異。這里按照蘋果文檔所述,重點對堆內存分配整理下。
首先,iOS和其它系統(tǒng)一樣,內存分頁,每頁4K。多個頁構成一個region統(tǒng)一管理,負責管理的對象是VM object,其中包含了pager、size、resident pages等諸多屬性。
不管是Objective-C的[NSObject alloc],還是C代碼的對內存分配,最終重任都會落到malloc庫上,釋放也是如此,最終都將使用malloc庫中的free()。
malloc 庫中有很多malloc的同族函數(shù)可以動態(tài)分配內存,會結合參數(shù)在free pages中進行最適分配。如果分配的內存比較大,可以直接使用vm_allocate,得到一個VM對象(與Linux類似),這個在實際使用前不分配 物理內存。malloc的內部實現(xiàn)都是開源的,感興趣的可以去了解去看。
此外,對于malloc,還有一個Zone的概念(貌似與 Linux的概念不完全相同),可以簡單理解為一組free page單元,可以統(tǒng)一管理操作。默認情況,在***次調用malloc時,系統(tǒng)會生成一個default zone,后續(xù)的默認分配在此進行。比如,malloc_zone_xxx()函數(shù)都是對特定的zone進行分配操作,執(zhí)行 zone->xxx()。
***強調一下iOS特別需要注意的點:
當前的主流iPhone實際物理內存都不超過1G,可以說不算大。不過和Android機比起來,我不得不為蘋果的設計稱贊,1G空間利用得如此高效,性能不差,也控制了發(fā)熱。
那 么在這僅有的1G內存中,iOS的操作系統(tǒng)更是拋棄了不必要的復雜——系統(tǒng)層面不支持App內存頁換出。當內存吃緊時,對于可以重新載入的只讀數(shù)據(jù)來說, 直接清理掉,而對于可寫的數(shù)據(jù),只能通過App自己去管理維護。內存緊張時,iOS會向App發(fā)起memory warning,不配合釋放足夠內存者,殺!
App調試時的物理內存情況
上 圖是使用Activity Monitor調試時的一個截圖,可以看到在盡量不釋放自身內存的情況下(為了bug調試特意這么做的),支付寶錢包的內存可以做到502M物理內存占 用。再稍微高一點點,系統(tǒng)就會連前臺運行的App一起Kill掉。留下一個Unknown的log。
3. 其它
基本的原理就簡要整理到此,如下是一些參考:
Memory Layout of C Programs
Anatomyof a program in memory
What and where are the stack and heap?
Memory Usage Performance Guidelines
A look at how malloc works on the Mac
分享題目:說說iOS與內存管理(上)
鏈接URL:http://www.5511xx.com/article/dhhepoj.html


咨詢
建站咨詢
