OC的內存管理
開始之前, 先思考一個問題:為什么要管理內存?
曾看到一個笑話, 一個程序員去面試iOS程序員,面試官問:iOS開發(fā)中為什么需要內存管理?
程序員淡定地說:內存有限,所以要管理內存啊.
答案很出乎意料,但是仔細想想,真是一語道破了本質.
那在內存有限的情況下, 為什么要管理內存呢?
在iOS開發(fā)中, 我們要保證有限的內存資源得到最大化的利用,當我們創(chuàng)建一個類的對象時, 對應的在內存中,就得到一個塊內存來存放這個對象的內容. 但是這個對象(或者理解成一塊內存), 可能被多個指針變量使用. 不要奇怪, 怎么又出現(xiàn)了指針變量. 這是因為,在objective-C中,我們都是通過對象的引用來操縱內存的. 它本質就是一個指針(該對象在內存中的地址). 這樣做的好處是快呀. 試想, 我們在開發(fā)中, 同一個對象可能被次使用, 如果直接操作對象本身,那么當我們把一個對象賦值給另一個對象的時候,就需要把該對象中的所有內容全部都挨個從該對象所在的內存中取出來,放到另外一塊內存中. 如果,我們使用一個對象的地址來使用對象,那么就僅僅把一個整形值賦值給另外一個對象的引用就OK了.
-
說了那么多,看一下內存的布局:
可執(zhí)行文件在內存中的布局
現(xiàn)在我們知道內存管理實際上是管理我們的對象,對于其他的非對象類型不需要內存管理(int,float,,,)
這是為什么呢?
這是因為,堆區(qū)需要程序員手動管理, 棧區(qū)內存由系統(tǒng)負責管理(申請和釋放).實際上,非對象類型的數(shù)據(jù)內容和對象類型的數(shù)據(jù)內容,一個放在棧里面,一個放在堆里面(這里暫時這么理解:其實和變量是否靜態(tài)以及是否是全局有關系), 本質上我們管理內存就是管理堆. 即便后來objective-C退出的ARC機制,也僅僅是為每個對象添加一個自己的引用計數(shù)器.(作用是記錄有多少"人"在使用它,或者說有多少指針在指向這塊內存),當我們創(chuàng)建對象,對象之間相互傳值的時候, 系統(tǒng)自動的加減引用計數(shù)的值代替程序員手動的管理內存.
注意:有些時候, 文中所指的對象和對象引用(指針)為同一概念, 但是對象的本質是對應堆區(qū)中的一塊內存這一點是不變的
回到主題:為什么要管理內存呢?不好回答. 我們可以取反唄, 如果不管理內存會怎么樣?
- 如果內存不管理, 那么手機中的內存資源將會被很快的用完.
- 如果內存得不到很好的管理, 可能會出現(xiàn)正在使用的對象,但是該對象所對應的內存已經(jīng)被系統(tǒng)釋放,甚至已被分配給別的對象. 造成野指針,甚至數(shù)據(jù)錯誤的現(xiàn)象.
- 如果內存得不到很好的管理,可能會出現(xiàn). 對象已經(jīng)沒有被使用了,但還沒有被釋放. 浪費內存.
- 如果內存得不到很好的管理,還會出現(xiàn)很多問題...
既然要管理內存,就是要避免出現(xiàn)以上情況
如何管理內存
objective-C中通過引用一個叫做引用計數(shù)器的機制,來管理內存. 它的作用就是記錄當前對象(一塊內存)在程序中,有多少"人"在使用它.或者說有多少指針正在指向它.如果,仍然有指針在指向這塊內存,而此時我們卻釋放了這塊內存,這時候,該指針就成野指針了.
管理內存需要遵循的一些原則:
- 自己生成的對象自己持有
- 非自己生成的對象自己也能持有
- 不在需要自己持有的對象時釋放
- 非自己持有的對象不能釋放
在objective-C中都提供一些,供我們持有和釋放以及銷毀內存的方法供程序員使用,以便需要的時候,調用對應的方法來恰當?shù)墓芾韮却?
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
+ (instancetype)alloc OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
- (void)dealloc OBJC_SWIFT_UNAVAILABLE("use 'deinit' to define a de-initializer");
分別對應下面的內存管理動作:
- 生成并持有 alloc ,new, copy等方法
- 持有 retain
- 釋放 release
- 銷毀 dealloc
在OC中通過alloc類方法,可以生成一個對象.也可以通過使用Copy,mutableCopy 來生成一個對象的副本. 返回一個指向這個對象的指針 , 這個對象是保存在內存中的堆區(qū)的, 可以通過一個相同類型的指針變量來接收這個指針,從而使用它.但是這個指針變量是存儲在棧區(qū)的. 不需要管理, 系統(tǒng)會在"必要的時刻" 彈出棧幀, 這個時候,這個指針變量所指向的內存會release.
生成并持有的使用場景:
到了總結的時候了:也就是說,objective-C中的內存管理,管理的是內存中堆區(qū)中存放的對象,通過為每個對象增添一個引用計數(shù)器來實現(xiàn), 我們需要根據(jù)代碼中有多少引用指向該對象來動態(tài)的增加(向對象發(fā)送retain消息)和減少(向對象發(fā)送release消息)引用計數(shù)器的值.
對于上文中所提到的內存管理需要遵循的原則沒有詳細說明:打算下一篇在ARC中說明.