iOS 基本記憶體管理-引用計數器

來源:互聯網
上載者:User

1.什麼是記憶體管理 行動裝置的記憶體極其有限,每個app所能佔用的記憶體是有限制的當app所佔用的記憶體較多時,系統會發出記憶體警告,這時得回收一些不需要再使用的記憶體空間。比如回收一些不需要使用的對象、變數等管理範圍:任何繼承了NSObject的對象需要去管理記憶體,但是對於對其他基礎資料型別 (Elementary Data Type)(int、char、float、double、struct、enum等)結構,枚舉等不用去關心記憶體複製代碼- (void)test{    int a = 20;        int b = 10;       Person *person = [[Person alloc] init];        // 方法未退出之前 這三行代碼在記憶體中}複製代碼  一旦test方法執行完畢,意味著局部變數的範圍也失效,那麼棧空間的局部變數系統會自動檢測回收。但是堆空間中動態產生的對象是還沒有被回收。   可以看出即使已經沒有指標指向動態產生的對象了,但還是沒有被回收,因此需要手動管理釋放。釋放的方法是為對象發送一條訊息。因此需要調用對象的某個方法來釋放對象。 那麼系統是怎麼知道此時的對象需不需要回收呢?這就涉及到了對象結構中的"引用計數"   2.對象結構 每個OC對象內部都有自己的引用計數器,它是一個整數,表示"對象被引用的次數",即有多少人正在使用這個OC對象每個OC對象內部會自動化佈建4個位元組的儲存空間來儲存引用計數器  3.引用計數器的作用 當使用alloc、new或者copy建立一個新對象時,新對象的引用計數器預設就是1當一個對象的引用計數器值為0時,對象佔用的記憶體就會被系統回收。換句話說,如果對象的計數器不為0,那麼在整個程式運行過程,它佔用的記憶體就不可能被回收,除非整個程式已經退出  4.操作對象引用計數器的方法 給對象發送一條retain訊息,可以使引用計數器值+1(retain方法返回對象本身)retain方法返回的是id類型,那麼哪個對象調用返回的就是自己給對象發送一條release訊息,可以使引用計數器值-1可以給對象發送retainCount訊息獲得當前的引用計數器值   5.對象的銷毀 當一個對象的引用計數器值為0時,那麼它將被銷毀,其佔用的記憶體被系統回收當一個對象被銷毀時,系統會自動向對象發送一條dealloc訊息一般會重寫dealloc方法,在這裡釋放相關資源,dealloc就像對象的遺言一旦重寫了dealloc方法,就必須調用[super dealloc],並且放在最後面調用不能直接調用dealloc方法一旦對象被回收了,它佔用的記憶體就不再可用,堅持使用會導致程式崩潰(野指標錯誤)  複製代碼    // alloc方法是給堆中分配記憶體 init方法和記憶體無關 此時retainCurrent為1    Person *p = [[Person alloc] init];        // 返回的就是對象本身 retainCurrent為2    [p retain];        // retainCurrent為1    [p release];     // retainCurrent為0 說明Person類對象被回收,那麼對應的在記憶體中的地址已經不可用了 此時的Person對象稱為“殭屍對象”但是此時p指標還是在指向Person類對象所對應的那塊停用地址此時的p指標稱為“野指標”    [p release];複製代碼   6.開發中要注意的記憶體管理 預設情況下,Xcode是不會管理殭屍對象的,即使使用了一塊被釋放的記憶體也不會報錯。為了方便調試,應該開啟殭屍對象監控。設定:   注意三個概念: 殭屍對象:已經被回收的對象,或者說對象所對應的記憶體位址已經停用對象稱為殭屍對象。殭屍對象不可用 野指標:指向一塊不可用記憶體地址或者指向殭屍對象的指標稱為野指標。給野指標發送訊息會報 EXC_BAD_ACCESS錯誤 null 指標:沒有指向任何指標變數稱為空白指標,也意味著指標變數所儲存的值為0,nil,NULL 這樣可以避免野指標錯誤的發生 複製代碼/********************************** Person.h **************************************/#import <Foundation/Foundation.h> @interface Person : NSObject @property int age; @end  /********************************** Person.m **************************************/#import "Person.h" @implementation Person // 重寫父類NSOjbct的遺言方法 對象在被釋放之前一定會調用dealloc方法 - (void)dealloc{    NSLog(@"對象在釋放之前會執行遺言方法被執行");        [super dealloc]; // 一定要調用 而且必須放在最後面}@end  /********************************** main.m **************************************/#import <Foundation/Foundation.h>#import "Person.h"  /*  main方法是一個死迴圈方法以保證程式能持續運行,除非使用者關閉程式或者是手機沒電,程式才能終止 那麼在main方法裡面的Person對象不就一直存在麼,因此必須在main方法裡面將對象回收 */int main(int argc, const char * argv[]){    // alloc方法是給堆中分配記憶體 init方法和記憶體無關 此時retainCurrent為1    Person *p = [[Person alloc] init];        // 返回的就是對象本身 retainCurrent為2    [p retain];        // retainCurrent為1    [p release];        /*        retainCurrent為0       說明Person類對象被回收,那麼對應的在記憶體中的地址已經不可用了        此時的Person對象稱為“殭屍對象”       此時p指標還是在指向Person類對象所對應的那塊停用地址,此時p指標稱為“野指標”    */    [p release];            /*        對象已經被回收,千萬別以為再給對象發送一個retain訊息對象就可以“起死回生”應該節哀順變        執行retain方法會報錯,此時的p指標已稱為野指標執行代碼回報:野指標錯誤     */        // [p retain];        /*        此時對象已經被回收稱為“殭屍對象了”不可以再訪問屬性        在執行p.age = 10;報錯:        -[Person setAge:]: message sent to deallocated instance  訊息發送給了已經被釋放的對象        再次證明“殭屍對象不可以用”     */                /*         一旦指標成為野指標再繼續向p指標所指的對象發送訊息就會報錯:Exc_BAd_ACCESS        說明訪問了一塊壞記憶體(已經被回收、停用記憶體) “野指標錯誤”         那麼此時在對象回收之後將指標變數清空        那麼棧中的指標變數就不會再指向堆中類對象的記憶體位址了    */    p = nil;        /*          指標變數內部所儲存的值已被清空,那麼指標已經無指向        再給指標發送任何訊息指標會無任何響應,而且也不報錯因為OC中沒有null 指標錯誤     */    [p release];    [p release];    [p release];    [p release];        return 0;

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.