黑馬程序員-內存管理

一. OC的內存管理的過程

        OC爲每個對象提供一個內部計數器,這個計數器跟蹤對象的引用計數,當對象被創建或拷貝時,引用計數爲1,每次保持對象時,調用retain接口,引用計數加1,如果不需要這個對象時調用release,引用計數減1,當對像的引用計數爲0時,系統就會釋放掉這塊內存,釋放對象調用dealloc。

for example:

    1.對象在完成創建的同時,內部會自動創建一個引用計數器,這個計數器,是系統用來判斷是否回收對象的唯一依據,當我們的引用計數retainCount 0的時候,系統會毫不猶豫回收當前對象

    2.[對象 release]  reatinCount - 1

    3.[對象 retain]   reatinCount + 1 ,返回self

    4.我們的引用計數retainCount 0 對象就被銷燬了

    5.dealloc函數,當一個對象要被銷燬的時候,系統會自動調用dealloc函數,通知對象你將要被銷燬

          內存管理原則(配對原則):只要出現了 new,alloc,retain,就一定配對出現一個release,autorelease


二.單個對象的內存管理

    

//定義了一個 Person類  
//Person.h
@interface Person : NSObject

@property int age;
- (void)run;
@end 

//Person.m
- (void)dealloc
{
    [super dealloc];
    
    NSLog(@"Person 被銷燬了");
}

//重寫description方法
- (NSString *)description
{
    return [NSString stringWithFormat:@"age = %d",_age];
}

- (void)run
{
    NSLog(@"人跑起來了");
}

於是在在主函數中開始了實驗

測試1:

void test1()
{
    //retainCount = 1
    Person * p = [[Person alloc] init];

    //retainCount = 0
    //系統已經將p所指向的對象回收了
    //EXC_BAD_ACCESS 訪問了不可訪問的內存空間
    //被系統回收的對象我們稱之爲殭屍對象
    //默認情況下xcode爲了提高編碼效率,不會時時檢查殭屍對象
    [p release];
 
    //不能調用run方法
    [p run];
 
}

結論:系統將對象回收後,對象變成殭屍對象,不能再調用對象方法

解決辦法:如果你確定當前作用於中的對象已經不會再被使用了,爲了防止野指針操作,通常我們會把不在使用的指針變量賦值爲nil  p = nil;


測試2

void test2()
{

     //內存泄漏第一種情況
     //1
     Person * p = [[Person alloc] init];
     
     p.age = 20;
     NSLog(@"%@",p);
     //2
     [p retain];
     
     //3
     [p retain];
     
     //2
     [p release];
     
     //只要對象的retainCount != 0 就會一直存在在內存中
     //內存泄漏指的就是,不再被使用的對象,一直在內存中沒有被銷燬

    
     //內存泄漏第二種情況
     //retainCount = 1
     Person * p = [[Person alloc] init];
     p.age = 20;
     [p run];   
     p = nil;
     [p release];//[nil release];
     */

結論:在上面的實驗中列出了兩種內存泄漏的可能,1.retainCount 不等於0    2.空指針release


測試3:

void test4()
{
    //1
    Person * p = [[Person alloc] init];
    
    p.age = 20;
    NSLog(@"%@",p);
    
    //0
    [p release];
   
    [p retain];
}

結論:

野指針操作,當一個對象retainCount已經爲0 時,調用retain方法,是不會使得對象起死回生的,同時還會發生野指針操作異常


三.多個對象的內存管理


剛剛只有一個人對象,現在添加一個Car對象,讓Person類包含Car類

@interface Person : NSObject
{
    Car * _car;
}

- (void)setCar:(Car *)car;
- (Car *)car;
- (void)drive;

@end



爲了防止內存泄漏,Person類銷燬時,Car也銷燬,於是重寫了Person類的

- (void)dealloc
{
    //目的是要保證在p對象存在的時候,car對象一定存在
    //對象p被銷燬的時候,
    [_car release]
    [super dealloc];
    NSLog(@"Person 被銷燬了");
}


四.手動內存管理時出現類之間相互引用的問題

@property(nonatomic,retain) Car * car;

@property (nonatomic,assign)Person * person;

當出現兩個類相互引用時,一定要有一個類使用assign,表示弱引用,如果都使用retain則會出現相互引用!!



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章