一、Instruments介紹
Instruments 一個(gè)很靈活的、強(qiáng)大的工具,是性能分析、動(dòng)態(tài)跟蹤 和分析OS X以及iOS代碼的測試工具,用它可以極為方便收集關(guān)于一個(gè)或多個(gè)系統(tǒng)進(jìn)程的性能和行為的數(shù)據(jù),并能及時(shí)隨著時(shí)間跟蹤而產(chǎn)生的數(shù)據(jù),并檢查所收集的數(shù)據(jù),還可以廣泛收集不同類型的數(shù)據(jù).也可以追蹤程序運(yùn)行的過程,這樣instrument就可以幫助我們了解用戶的應(yīng)用程序和操作系統(tǒng)的行為。
總結(jié)一下instrument能做的事情:
1. Instruments是用于動(dòng)態(tài)調(diào)追蹤和分析OS X和iOS的代碼的性能分析和測試工具;
2.Instruments支持多線程的調(diào)試;
3.可以用Instruments去錄制和回放,圖形用戶界面的操作過程
4.可將錄制的圖形界面操作和Instruments保存為模板,供以后訪問使用。
instrument還可以:
1.追蹤代碼中的(甚至是那些難以復(fù)制的)問題;
2.分析程序的性能;
3.實(shí)現(xiàn)程序的自動(dòng)化測試;
4.部分實(shí)現(xiàn)程序的壓力測試;
5.執(zhí)行系統(tǒng)級(jí)別的通用問題追蹤調(diào)試;
6.使你對(duì)程序的內(nèi)部運(yùn)行過程更加了解。
打開方式:
Xcode -> Open Developer Tool -> Instruments

其中比較常用的有四種:
- Allocations:用來檢查內(nèi)存分配,跟蹤過程的匿名虛擬內(nèi)存和堆的對(duì)象提供類名和可選保留/釋放歷史
- Leaks:一般的查看內(nèi)存使用情況,檢查泄漏的內(nèi)存,并提供了所有活動(dòng)的分配和泄漏模塊的類對(duì)象分配統(tǒng)計(jì)信息以及內(nèi)存地址歷史記錄
- Time Profiler:分析代碼的執(zhí)行時(shí)間,執(zhí)行對(duì)系統(tǒng)的CPU上運(yùn)行的進(jìn)程低負(fù)載時(shí)間為基礎(chǔ)采樣
- Zombies:檢查是否訪問了僵尸對(duì)象
其他的:
- Blank:創(chuàng)建一個(gè)空的模板,可以從Library庫中添加其他模板
- Activity Monitor:顯示器處理的CPU、內(nèi)存和網(wǎng)絡(luò)使用情況統(tǒng)計(jì)
- Automation:用JavaScript語言編寫,主要用于分析應(yīng)用的性能和用戶行為,模仿/擊發(fā)被請(qǐng)求的事件,利用它可以完成對(duì)被測應(yīng)用的簡單的UI測試及相關(guān)功能測試
- Cocoa Layout:觀察約束變化,找出布局代碼的問題所在。
- Core Animation:用來檢測Core Animation性能的,給我們提供了周期性的FPS,并且考慮到了發(fā)生在程序之外的動(dòng)畫,界面滑動(dòng)FPS可以進(jìn)行測試
- Core Data:監(jiān)測讀取、緩存未命中、保存等操作,能直觀顯示是否保存次數(shù)遠(yuǎn)超實(shí)際需要
- Energy Diagnostic :用于Xcode下的Instruments來分析手機(jī)電量消耗的。(必須是真機(jī)才有電量)
- GPU Driver :可以測量GPU的利用率,同樣也是一個(gè)很好的來判斷和GPU相關(guān)動(dòng)畫性能的指示器。它同樣也提供了類似Core Animtaion那樣顯示FPS的工具。
- Network:分析應(yīng)用程序如何使用TCP / IP和UDP / IP連接使用連接儀器。就是檢查手機(jī)網(wǎng)速的。(這個(gè)最好是真機(jī))
二、Allocations(分配)
1.內(nèi)存分類:
- Leaked memory:泄漏的內(nèi)存,如為對(duì)象A申請(qǐng)了內(nèi)存空間,之后再也沒用到A,也沒有釋放A導(dǎo)致內(nèi)存泄漏(野指針。。。)
- Abandoned memory:被遺棄的內(nèi)存,如循環(huán)引用,遞歸不斷申請(qǐng)內(nèi)存而導(dǎo)致的內(nèi)存泄漏
- Cached memory:緩存的內(nèi)存
2.Abandoned memory
其中內(nèi)存泄漏我們可以用Leaks,野指針可以用Zombies(僵尸對(duì)象),而在這里我們就可以用Allocations來檢測Abandoned memory的內(nèi)存。

即我們采用Generational Analysis的方法來分析,反復(fù)進(jìn)入退出某一場景,查看內(nèi)存的分配與釋放情況,以定位哪些對(duì)象是屬于Abandoned Memory的范疇。
在Allocations工具中,有專門的Generational Analysis設(shè)置,如下:

我們可以在程序運(yùn)行時(shí),在進(jìn)入某個(gè)模塊前標(biāo)記一個(gè)Generation,這樣會(huì)生成一個(gè)快照。然后進(jìn)入、退出,再標(biāo)記一個(gè)Generation,如下圖:

在詳情面板中我們可以看到兩個(gè)Generation間內(nèi)存的增長情況,其中就可能存在潛在的被遺棄的對(duì)象,如下圖:

其中g(shù)rowth就是我們增長的內(nèi)存,GenerationA是程序啟動(dòng)到進(jìn)入該場景增長的內(nèi)存,GenerationB就是第二次進(jìn)入該場景所增長的內(nèi)存,查看子類可以發(fā)現(xiàn)有兩個(gè)管理類造成了Abandoned memory。
3.設(shè)置Generations
使用instrument測試內(nèi)存泄露 工具 Allocations 測試是否內(nèi)存泄露 使用標(biāo)記,可以更省事省力的測試頁面是否有內(nèi)存泄露
1)設(shè)置Generations

2)選擇mark generation

3)使用方法 在進(jìn)入測試頁面之前,mark一下----->進(jìn)入頁面----->退出----->mark------>進(jìn)入------->退出------->mark------>進(jìn)入如此往復(fù)5、6次,就可以看到如下結(jié)果

這種情況下是內(nèi)存有泄露,看到每次的增量都是好幾百K或者上M的,都是屬于內(nèi)存有泄露的,這時(shí)候就需要檢測下代碼一般情況下,100K以下都屬于正常范圍,growth表示距離你上次mark的增量
三、Leaks(泄漏)
1.內(nèi)存溢出和內(nèi)存泄漏的區(qū)別
內(nèi)存溢出 out of memory,是指程序在申請(qǐng)內(nèi)存時(shí),沒有足夠的內(nèi)存空間供其使用,出現(xiàn)out of memory;比如申請(qǐng)了一個(gè)integer,但給它存了long才能存下的數(shù),那就是內(nèi)存溢出。
內(nèi)存泄露 memory leak,是指程序在申請(qǐng)內(nèi)存后,無法釋放已申請(qǐng)的內(nèi)存空間,一次內(nèi)存泄露危害可以忽略,但內(nèi)存泄露堆積后果很嚴(yán)重,無論多少內(nèi)存,遲早會(huì)被占光。
memory leak會(huì)最終會(huì)導(dǎo)致out of memory!
在前面的ALLcations里面我們提到過內(nèi)存泄漏就是應(yīng)該釋放而沒有釋放的內(nèi)存。而內(nèi)存泄漏分為兩種:Leaked Memory 和 Abandoned Memory。前面我們講到了如何找到Abandoned Memory被遺忘的內(nèi)存,現(xiàn)在我們研究的就是Leaked Memory。
以發(fā)生的方式來分類,內(nèi)存泄漏可以分為4類:
常發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼會(huì)被多次執(zhí)行到,每次被執(zhí)行的時(shí)候都會(huì)導(dǎo)致一塊內(nèi)存泄漏。
偶發(fā)性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只有在某些特定環(huán)境或操作過程下才會(huì)發(fā)生。常發(fā)性和偶發(fā)性是相對(duì)的。對(duì)于特定的環(huán)境,偶發(fā)性的也許就變成了常發(fā)性的。所以測試環(huán)境和測試方法對(duì)檢測內(nèi)存泄漏至關(guān)重要。
一次性內(nèi)存泄漏。發(fā)生內(nèi)存泄漏的代碼只會(huì)被執(zhí)行一次,或者由于算法上的缺陷,導(dǎo)致總會(huì)有一塊僅且一塊內(nèi)存發(fā)生泄漏。比如,在類的構(gòu)造函數(shù)中分配內(nèi)存,在析構(gòu)函數(shù)中卻沒有釋放該內(nèi)存,所以內(nèi)存泄漏只會(huì)發(fā)生一次。
隱式內(nèi)存泄漏。程序在運(yùn)行過程中不停的分配內(nèi)存,但是直到結(jié)束的時(shí)候才釋放內(nèi)存。嚴(yán)格的說這里并沒有發(fā)生內(nèi)存泄漏,因?yàn)樽罱K程序釋放了所有申請(qǐng)的內(nèi)存。但是對(duì)于一個(gè)服務(wù)器程序,需要運(yùn)行幾天,幾周甚至幾個(gè)月,不及時(shí)釋放內(nèi)存也可能導(dǎo)致最終耗盡系統(tǒng)的所有內(nèi)存。所以,我們稱這類內(nèi)存泄漏為隱式內(nèi)存泄漏。
影響:從用戶使用程序的角度來看,內(nèi)存泄漏本身不會(huì)產(chǎn)生什么危害,作為一般的用戶,根本感覺不到內(nèi)存泄漏的存在。真正有危害的是內(nèi)存泄漏的堆積,這會(huì)最終消耗盡系統(tǒng)所有的內(nèi)存。從這個(gè)角度來說,一次性內(nèi)存泄漏并沒有什么危害,因?yàn)樗粫?huì)堆積,而隱式內(nèi)存泄漏危害性則非常大,因?yàn)檩^之于常發(fā)性和偶發(fā)性內(nèi)存泄漏它更難被檢測到。
下邊我們介紹Instruments里面的Leaked的用法,首先打開Leaked,跑起工程來,點(diǎn)擊要測試的頁面,如果有內(nèi)存泄漏,會(huì)出現(xiàn)下圖中的紅色的?。然后按照后邊的步驟進(jìn)行修復(fù)即可


上面的舊版的樣式,下面的是新版的樣式,基本操作差不多


在詳情面板選中顯示的若干條中的一條,雙擊,會(huì)自動(dòng)跳到內(nèi)存泄露代碼處,然后點(diǎn)擊右上角 Xcode 圖標(biāo)進(jìn)行修改。
下圖是對(duì)Leaked頁面進(jìn)一步的理解:

內(nèi)存泄漏動(dòng)態(tài)分析技巧:
- 在 Display Settings 界面建議把 Snapshot Interval (snap??t, 數(shù)據(jù)快照)間隔時(shí)間設(shè)置為10秒,勾選Automatic Snapshotting,Leaks 會(huì)自動(dòng)進(jìn)行內(nèi)存捕捉分析。(新版本直接在底部修改)
- 熟練使用 Leaks 后會(huì)對(duì)內(nèi)存泄漏判斷更準(zhǔn)確,在可能導(dǎo)致泄漏的操作里,在你懷疑有內(nèi)存泄漏的操作前和操作后,可以點(diǎn)擊 Snapshot Now 進(jìn)行手動(dòng)捕捉。
- 開始時(shí)如果設(shè)備性能較好,可以把自動(dòng)捕捉間隔設(shè)置為 5 秒鐘。
- 使用ARC的項(xiàng)目,一般內(nèi)存泄漏都是 malloc、自定義結(jié)構(gòu)、資源引起的,多注意這些地方進(jìn)行分析。
- 開啟ARC后,內(nèi)存泄漏的原因
開啟了ARC并不是就不會(huì)存在內(nèi)存問題,蘋果有句名言:ARC is only for NSObject。
注:如果你的項(xiàng)目使用了ARC,隨著你的操作,不斷開啟或關(guān)閉視圖,內(nèi)存可能持續(xù)上升,但這不一定表示存在內(nèi)存泄漏,ARC釋放的時(shí)機(jī)是不固定的。
這里對(duì) Display Settings中 的 Call tree 選項(xiàng)做一下說明 [官方user guide翻譯]:
- Separate By Thread:線程分離,只有這樣才能在調(diào)用路徑中能夠清晰看到占用CPU最大的線程.每個(gè)線程應(yīng)該分開考慮。只有這樣你才能揪出那些大量占用CPU的"重"線程,按線程分開做分析,這樣更容易揪出那些吃資源的問題線程。特別是對(duì)于主線程,它要處理和渲染所有的接口數(shù)據(jù),一旦受到阻塞,程序必然卡頓或停止響應(yīng)。
- Invert Call Tree:從上到下跟蹤堆棧信息.這個(gè)選項(xiàng)可以快捷的看到方法調(diào)用路徑最深方法占用CPU耗時(shí)(這意味著你看到的表中的方法,將已從第0幀開始取樣,這通常你是想要的,只有這樣你才能看到CPU中花費(fèi)時(shí)間最深的方法),比如FuncA{FunB{FunC}},勾選后堆棧以C->B->A把調(diào)用層級(jí)最深的C顯示最外面.反向輸出調(diào)用樹。把調(diào)用層級(jí)最深的方法顯示在最上面,更容易找到最耗時(shí)的操作。
- Hide Missing Symbols:如果dSYM無法找到你的APP或者調(diào)用系統(tǒng)框架的話,那么表中將看到調(diào)用方法名只能看到16進(jìn)制的數(shù)值,勾選這個(gè)選項(xiàng)則可以隱藏這些符號(hào),便于簡化分析數(shù)據(jù).
- Hide System Libraries:表示隱藏系統(tǒng)的函數(shù),調(diào)用這個(gè)就更有用了,勾選后耗時(shí)調(diào)用路徑只會(huì)顯示app耗時(shí)的代碼,性能分析普遍我們都比較關(guān)系自己代碼的耗時(shí)而不是系統(tǒng)的.基本是必選項(xiàng).注意有些代碼耗時(shí)也會(huì)納入系統(tǒng)層級(jí),可以進(jìn)行勾選前后前后對(duì)執(zhí)行路徑進(jìn)行比對(duì)會(huì)非常有用.因?yàn)橥ǔD阒魂P(guān)心cpu花在自己代碼上的時(shí)間不是系統(tǒng)上的,隱藏系統(tǒng)庫文件。過濾掉各種系統(tǒng)調(diào)用,只顯示自己的代碼調(diào)用。隱藏缺失符號(hào)。如果 dSYM 文件或其他系統(tǒng)架構(gòu)缺失,列表中會(huì)出現(xiàn)很多奇怪的十六進(jìn)制的數(shù)值,用此選項(xiàng)把這些干擾元素屏蔽掉,讓列表回歸清爽。
- Show Obj-C Only:只顯示oc代碼 ,如果你的程序是像OpenGl這樣的程序,不要勾選側(cè)向因?yàn)樗锌赡苁荂++的
- Flatten Recursion:遞歸函數(shù), 每個(gè)堆棧跟蹤一個(gè)條目,拼合遞歸。將同一遞歸函數(shù)產(chǎn)生的多條堆棧(因?yàn)檫f歸函數(shù)會(huì)調(diào)用自己)合并為一條。
- Top Functions:找到最耗時(shí)的函數(shù)或方法。 一個(gè)函數(shù)花費(fèi)的時(shí)間直接在該函數(shù)中的總和,以及在函數(shù)調(diào)用該函數(shù)所花費(fèi)的時(shí)間的總時(shí)間。因此,如果函數(shù)A調(diào)用B,那么A的時(shí)間報(bào)告在A花費(fèi)的時(shí)間加上B.花費(fèi)的時(shí)間,這非常真有用,因?yàn)樗梢宰屇忝看蜗碌秸{(diào)用堆棧時(shí)挑最大的時(shí)間數(shù)字,歸零在你最耗時(shí)的方法。
四、Time Profiler(時(shí)間分析器)
用來檢測app中每個(gè)方法所用的時(shí)間,并且可以排序,并查找出哪些函數(shù)占用了大量時(shí)間。
使用Time Profile前有兩點(diǎn)需要注意的地方:
1、一定要使用真機(jī)調(diào)試
在開始進(jìn)行應(yīng)用程序性能分析的時(shí)候,一定要使用真機(jī)。因?yàn)槟M器運(yùn)行在Mac上,然而Mac上的CPU往往比iOS設(shè)備要快。相反,Mac上的GPU和iOS設(shè)備的完全不一樣,模擬器不得已要在軟件層面(CPU)模擬設(shè)備的GPU,這意味著GPU相關(guān)的操作在模擬器上運(yùn)行的更慢,尤其是使用CAEAGLLayer來寫一些OpenGL的代碼時(shí)候,這就導(dǎo)致模擬器性能數(shù)據(jù)和用戶真機(jī)使用性能數(shù)據(jù)相去甚遠(yuǎn)
2、應(yīng)用程序一定要使用發(fā)布配置
在發(fā)布環(huán)境打包的時(shí)候,編譯器會(huì)引入一系列提高性能的優(yōu)化,例如去掉調(diào)試符號(hào)或者移除并重新組織代碼。另iOS引入一種"Watch Dog"[看門狗]機(jī)制,不同的場景下,“看門狗”會(huì)監(jiān)測應(yīng)用的性能,如果超出了該場景所規(guī)定的運(yùn)行時(shí)間,“看門狗”就會(huì)強(qiáng)制終結(jié)這個(gè)應(yīng)用的進(jìn)程。開發(fā)者可以crashlog看到對(duì)應(yīng)的日志,但Xcode在調(diào)試配置下會(huì)禁用"Watch Dog"
1)界面詳情:

2)詳細(xì)面板

主要是看Call Tree和Sample List這兩種視圖:
3)調(diào)用樹

Running Time:函數(shù)運(yùn)行的時(shí)間,這個(gè)時(shí)間是累積時(shí)間
Self:在棧頂次數(shù)
Symbol Name:被調(diào)用函數(shù)的符號(hào)信息
4)詳情面板更多的信息選項(xiàng)

5)樣本列表

五、Zombies(僵尸)
1.概念
翻譯英文:專注于檢測過度釋放的“僵尸”對(duì)象。還提供了數(shù)據(jù)對(duì)象分配的類以及所有活動(dòng)分配內(nèi)存地址的歷史。
這里我們可以看到一個(gè)詞語叫“over-release”,過度釋放。我們在項(xiàng)目中見到最多的就是“EXC_BAD_ACCESS”或者是這樣的:Thread 1: Program received signal:"EXC_BAD_ACCESS",這就是訪問了被釋放的內(nèi)存地址造成的。
過度釋放,是對(duì)同一個(gè)對(duì)象釋放了過多的次數(shù),其實(shí)當(dāng)引用計(jì)數(shù)降到0時(shí),對(duì)象占用的內(nèi)存已經(jīng)被釋放掉,此時(shí)指向原對(duì)象的指針就成了“懸垂指針”,如若再對(duì)其進(jìn)行任何方法的調(diào)用,(原則上)都會(huì)直接crash(然而由于某些特殊的情況,不會(huì)馬上crash)。過度釋放簡單的說就是對(duì)release的對(duì)象再release,就是過度釋放。
我們需要知道這幾個(gè)概念:
1、內(nèi)存泄漏:對(duì)象使用完沒有釋放,導(dǎo)致內(nèi)存浪費(fèi)。
2、僵尸對(duì)象:已經(jīng)被銷毀的對(duì)象(不能再使用的對(duì)象)
3、野指針:指向僵尸對(duì)象(不可用內(nèi)存)的指針。給野指針發(fā)消息會(huì)報(bào)EXC_BAD_ACCECC錯(cuò)誤。
4、空指針:沒有指向儲(chǔ)存空間的指針(里面存的是nil,也就是0)。在oc中使用空指針調(diào)中方法不會(huì)報(bào)錯(cuò)。
注意:為了避免野指針錯(cuò)誤的常見方法:在對(duì)象被銷毀之后,將指向?qū)ο蟮闹羔樧優(yōu)榭罩羔槨?/p>
對(duì)于過度釋放的問題,可以直接使用Zombie,當(dāng)過度釋放發(fā)生時(shí)會(huì)立即停在發(fā)生問題的位置,同時(shí)結(jié)合內(nèi)存分配釋放歷史和調(diào)用棧,可以發(fā)現(xiàn)問題。至于上文提到的不會(huì)crash的原因,其實(shí)有很多,比如:
對(duì)象內(nèi)存釋放時(shí),所用內(nèi)存并沒有完全被擦除,仍有舊對(duì)象部分?jǐn)?shù)據(jù)可用
原內(nèi)存位置被寫入同類或同樣結(jié)構(gòu)的數(shù)據(jù)
2.原理
我們將僵尸對(duì)象“復(fù)活”的目的:僵尸對(duì)象就是讓已經(jīng)釋放了的對(duì)象重新復(fù)活,便于調(diào)試;是為了讓已經(jīng)釋放了的對(duì)象在被再次訪問時(shí)能夠輸出一些錯(cuò)誤信息。其實(shí)這里的“復(fù)活”并不是真的復(fù)活,而是強(qiáng)行不死:這么說吧 相當(dāng)于 他的RC=0的時(shí)候 系統(tǒng)再強(qiáng)行讓他RC=1,順便打上一個(gè)標(biāo)記 zoom,等到你去掉那個(gè)溝以后 系統(tǒng)會(huì)把帶有標(biāo)記zoom的對(duì)象RC=0。
3.用法
下邊是Instruments里面的Zombies的用法:
在Launch Configuration中勾選Record reference counts和Enable NSZombie detection。其中Recordreference counts是顯示引用計(jì)數(shù),Enable NSZombie detection是能夠檢測僵尸對(duì)象。

這樣在程序運(yùn)行的時(shí)候,如果發(fā)現(xiàn)僵尸對(duì)象它就會(huì)彈出一個(gè)對(duì)話框,點(diǎn)擊其中“→”按鈕,在屏幕的下方會(huì)顯示僵尸對(duì)象的詳細(xì)信息,下圖可以看到僵尸對(duì)象的引用計(jì)數(shù)變化情況。

注意:Zombies模版在使用的時(shí)候會(huì)導(dǎo)致內(nèi)存的飆升,這是因?yàn)樗斜会尫诺膶?duì)象被僵尸對(duì)象取代,并未真的釋放掉,在結(jié)束Zombies時(shí)會(huì)釋放,這是預(yù)知行為,這就意味著instrument里的其它工具和Zombies是不能同時(shí)使用的,Zombies會(huì)導(dǎo)致其它的數(shù)據(jù)不準(zhǔn)。包括leaks,你也不應(yīng)該把它加到Zombies模版中,即使這么做了結(jié)果也沒什么意義。對(duì)于iOS應(yīng)用來說,在用Zombies模版時(shí)使用iOS模擬器比真機(jī)要好。
另外XCode也提供了手動(dòng)設(shè)置NSZombieEnabled環(huán)境變量的方法,不過設(shè)置NSZombieEnabled為True后,會(huì)導(dǎo)致內(nèi)存占用的增長,同時(shí)會(huì)影響Leaks工具的調(diào)試,這是因?yàn)樵O(shè)置NSZombieEnabled會(huì)用僵尸對(duì)象來代替已釋放對(duì)象。
點(diǎn)擊Product菜單Edit Scheme打開該頁面,然后勾選Enable Zombie Objects復(fù)選框:

最后提醒的是NSZombieEnabled只能在調(diào)試的時(shí)候使用,千萬不要忘記在產(chǎn)品發(fā)布的時(shí)候去掉,因?yàn)镹SZombieEnabled不會(huì)真正去釋放dealloc對(duì)象的內(nèi)存,一直開啟的話,該死去的對(duì)象會(huì)一直存在,后果可想而知,自重!
六、擴(kuò)展
-
野指針
- C語言: 當(dāng)我們聲明1個(gè)指針變量,沒有為這個(gè)指針變量賦初始值.這個(gè)指針變量的值是1個(gè)垃圾指 指向1塊隨機(jī)的內(nèi)存空間。
- OC語言: 指針指向的對(duì)象已經(jīng)被回收掉了.這個(gè)指針就叫做野指針.
- 僵尸對(duì)象
-
內(nèi)存回收的本質(zhì).
- 申請(qǐng)1塊空間,實(shí)際上是向系統(tǒng)申請(qǐng)1塊別人不再使用的空間.
- 釋放1塊空間,指的是占用的空間不再使用,這個(gè)時(shí)候系統(tǒng)可以分配給別人去使用.
- 在這個(gè)個(gè)空間分配給別人之前 數(shù)據(jù)還是存在的.
- OC對(duì)象釋放以后,表示OC對(duì)象占用的空間可以分配給別人.
- 但是再分配給別人之前 這個(gè)空間仍然存在 對(duì)象的數(shù)據(jù)仍然存在.
- 僵尸對(duì)象: 1個(gè)已經(jīng)被釋放的對(duì)象 就叫做僵尸對(duì)象.
-
使用野指針訪問僵尸對(duì)象.有的時(shí)候會(huì)出問題,有的時(shí)候不會(huì)出問題.
- 當(dāng)野指針指向的僵尸對(duì)象所占用的空間還沒有分配給別人的時(shí)候, - 這個(gè)時(shí)候其實(shí)是可以訪問的.
- 因?yàn)閷?duì)象的數(shù)據(jù)還在.
- 當(dāng)野指針指向的對(duì)象所占用的空間分配給了別人的時(shí)候 這個(gè)時(shí)候訪問就會(huì)出問題.
- 所以,你不要通過1個(gè)野指針去訪問1個(gè)僵尸對(duì)象.
- 雖然可以通過野指針去訪問已經(jīng)被釋放的對(duì)象,但是我們不允許這么做.
-
僵尸對(duì)象檢測.
- 默認(rèn)情況下. Xcode不會(huì)去檢測指針指向的對(duì)象是否為1個(gè)僵尸對(duì)象. 能訪問就訪問 不能訪問就報(bào)錯(cuò).
- 可以開啟Xcode的僵尸對(duì)象檢測.
- 那么就會(huì)在通過指針訪問對(duì)象的時(shí)候,檢測這個(gè)對(duì)象是否為1個(gè)僵尸對(duì)象 如果是僵尸對(duì)象 就會(huì)報(bào)錯(cuò).
- 為什么不默認(rèn)開啟僵尸對(duì)象檢測呢?
- 因?yàn)橐坏╅_啟,每次通過指針訪問對(duì)象的時(shí)候.都會(huì)去檢查指針指向的對(duì)象是否為僵尸對(duì)象.
- 那么這樣的話 就影響效率了.
-
- 如何避免僵尸對(duì)象報(bào)錯(cuò).
- 當(dāng)1個(gè)指針變?yōu)橐爸羔樢院? 就把這個(gè)指針的值設(shè)置為nil
- 僵尸對(duì)象無法復(fù)活.
- 當(dāng)1個(gè)對(duì)象的引用計(jì)數(shù)器變?yōu)?以后 這個(gè)對(duì)象就被釋放了.
- 就無法取操作這個(gè)僵尸對(duì)象了. 所有對(duì)這個(gè)對(duì)象的操作都是無效的.
- 因?yàn)橐坏?duì)象被回收 對(duì)象就是1個(gè)僵尸對(duì)象 而訪問1個(gè)僵尸對(duì)象 是沒有意義.
好了,以上就是對(duì)于
Instruments工具的使用總結(jié)
喜歡的就點(diǎn)個(gè)贊??吧
參考文章
Allocations:Xcode8 Instruments 測試工具使用三
Leaks:Xcode 8 Instruments 學(xué)習(xí)(一)
Time Profiler:Xcode 8 Instruments 學(xué)習(xí)(二)
Zombies:Instruments性能檢測