Objective-C 【單個對象記憶體管理】

來源:互聯網
上載者:User

標籤:objective-c   單個對象記憶體管理   手動記憶體管理   

———————————————————————————————————————————
單個對象記憶體管理

(1)野指標
①定義了一個指標變數,但是並沒有賦初值,它隨機指向一個東西
②某指標變數指向的記憶體空間被釋放掉了(指向殭屍對象的指標)

(2)殭屍對象
已經被銷毀的對象(無法被使用的對象)

(3)null 指標
沒有指向儲存空間的指標(裡面存的是nil,也就是0)
給null 指標發訊息是沒有任何反應的,不會提示出錯



代碼:

#import <Foundation/Foundation.h>

@interface Person : NSObject
-(void)run;
@end

@implementation Person
-(void)run
{
    NSLog(@"run!");
}
- (void)dealloc
{
    NSLog(@"retainCount的結果為0,對象記憶體被釋放!");
    [super dealloc];
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p=[[Person alloc]init];
        NSLog(@"[p retainCount]=%tu",[p retainCount]);  //值為1
        
        [p run];
        NSLog(@"[p retainCount]=%tu",[p retainCount]);  //值還是為1,當前只有一個使用對象p的,也就是他自己,引用對象p的次數並沒有增加
        
        [p retain];
        NSLog(@"[p retainCount]=%tu",[p retainCount]);  //值為2
        
        [p release];
        NSLog(@"[p retainCount]=%tu",[p retainCount]);  //值為1
        
        [p release];//這裡的計數器值為0,記憶體被釋放
        
 //       [p run];    //記憶體釋放之後run方法還是可以調用的
//        那麼問題來了,上面run方法是在對象p的堆區記憶體被釋放之後調用的,為什麼還會調用成功呢?現在我們就來解決也是上節課遺留的問題
//        首先當p對象被release之後(記憶體被釋放),p就是一個野指標(殭屍對象)了
//        我們知道,雖然p在堆區的記憶體空間被釋放了,但是記憶體空間是不會變的還在那兒,棧區中也存在p。只是p已經失去了那一部分記憶體的管理權。如果此時你非要去使用這塊空間的話,且這塊記憶體空間沒有分配給其他的程式,其實還是能擷取到內容的。但是如果這塊釋放了的空間又被分配給其他的變數或者程式,這時候使用就不對了。
//        而且還有一點,就是上面釋放之後又調用run方法,不一定能百分百的調用,可能10次會出現一次調用錯誤的情況,這也就是野指標的危險。所以說,就不能用殭屍對象調用!!調用是完全無意義的!
        
//        [p retain];
//        這樣是完全錯誤的,我們上面已經將p所指向的對象記憶體釋放,那麼該對象就成為了殭屍對象,我們就不能夠這樣讓其複活(這樣硬來得到的值也是錯誤的結果)
//        為了避免我們使用殭屍對象,我們可以做這樣一個處理
         p=nil;
//        這樣處理過後,編譯器在執行下列語句的時候就不會報錯了。
        [p run];//不會執行,因為p為nil
        [p retain];//也不會讓計數+1,還是因為p為nil(空值)
         NSLog(@"[p retainCount]=%tu”,p.retainCount);
//點文法(  這裡相當於將p.retainCount——>[p  retainCount]  )

    }
    return 0;
}


★那麼我們應該怎麼防止野指標的調用呢?




操作步驟就是上面的兩幅圖了,將第二幅表徵圖記的地方打勾,那麼再使用野指標運行就會報錯了!
Enable Zombie Objects 就是開啟殭屍模式~


★★★關於nil和Nil以及NULL的區別

nil:首先這是一個null 指標,而且這是一個OC的對象,是一個對象值,如果我們把一個對象設為空白的話,我們就要設為nil  (  #define nil ((id) 0)   )

Nil:這是一個類對象值,如果把一個類對象設為空白,那麼我們就要設為Nil

NULL:是一個通用指標(泛型指標) (    #define NULL ((void *) 0 )   )

NSNull: [ NSNull  null ]  是一個對象,用在不能使用nil的場合


還有最後一點我們 需要注意的,那就是當我們釋放了一個對象的記憶體空間,讓該對象成為了殭屍對象,那麼是不能夠  用 [p  retain];  讓它複活的。在上面的程式中有體現。


(4)記憶體流失

代碼:

#import <Foundation/Foundation.h>

@interface Car : NSObject
-(void)run:(Car *)cccc;
@end

@implementation Car
- (void)dealloc
{
    NSLog(@"釋放記憶體!");
    [super dealloc];
}

-(void)run:(Car *)cccc
{
    NSLog(@"車在跑");
    [cccc retain];//在方法內部使用retain讓cccc的計數+1
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
//        (4)記憶體流失問題
        
//        ① retain 的次數 和 release 的次數 不匹配
        
//        Car *car=[Car new];
//        NSLog(@"car->retainCount=%tu",car.retainCount);//1
//        
//        [car retain];
//        [car retain];
//        [car retain];
//        
//        NSLog(@"car->retainCount=%tu",car.retainCount);//4
//        
//        [car release];
//        
//        NSLog(@"car->retainCount=%tu",car.retainCount);//3
////        顯然  retain 的次數 和 release 的次數 是不匹配的。retainCount 不為0,那麼空間自然沒有被回收釋放
////        如果不想讓記憶體流失,那麼必須 retain + new = release  (增加引用計數=減少引用計數)
        
////        ②對象在使用過程中被賦值了nil
        
//        Car *car1=[Car new];
//        
//        [car1 retain];
//        [car1 retain];
//        [car1 retain];
//        NSLog(@"car1->retainCount=%tu",car1.retainCount);//4
//        
//        car1=nil;
//        [car1 release];//其實這四條release語句是沒有作用的 ,是 [nil release]; ,我們知道向nil發送什麼指令都不會報錯,但是此時原對象car1的空間是沒有被釋放的,所以說最後car1的記憶體還是被泄漏了。
//        [car1 release];
//        [car1 release];
//        [car1 release];
//        
//        NSLog(@"car1->retainCount=%tu",car1.retainCount);//0,此時的0說明不了任何問題,並不是我們成功釋放記憶體,也不會列印dealloc中的語句
        
//        ③在方法中不當的使用了retain
        
//        Car *car2=[Car new];
//        [car2 run:car2];//我們將 car2 自己作為參數傳進去run方法,然後在run方法的內部retain,那麼car2->retainCount=2,所以說這裡如果只release是不夠的,應該release兩次才能釋放完記憶體
    }
    return 0;
}


———————————————————————————————————————————

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

Objective-C 【單個對象記憶體管理】

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.