iOSMRC手动释放对象野指针问题

在手动使用的时候有可能会遇到野指针问题,比如下面例子:

    ************************************************************
    /***   DogModel.h ***/
    ************************************************************
    #import 
    
    NS_ASSUME_NONNULL_BEGIN
    @interface DogModel : NSObject
    
    @property(nonatomic,copy)NSString *dogName;
    
    -(void)doing;
    
    @end
    
    NS_ASSUME_NONNULL_END
    
    ************************************************************
    /***   DogModel.m ***/
    ************************************************************
    #import "DogModel.h"
    @implementation DogModel
    -(void)doing{
        NSLog(@"%@ 会汪汪汪!",self.dogName);
    }
    -(void)dealloc{
        NSLog(@"DogModel = (%@)dealloc method.",self.dogName);
        [super dealloc];
    }
    @end
    
    
    ************************************************************
    /***   UserModel.h ***/
    ************************************************************
    #import 
    
    NS_ASSUME_NONNULL_BEGIN
    
    @class DogModel;
    
    @interface UserModel : NSObject
    
    @property(nonatomic,copy)NSString *UserName;
    
    - (void)setDog:(DogModel *) dog;
    -(DogModel*)Dog;
    
    @end
    
    NS_ASSUME_NONNULL_END
    ************************************************************
    /***   UserModel.m ***/
    ************************************************************
    #import "UserModel.h"
    
    @interface UserModel ()
    {
        DogModel *_Dog;
    }
    @end
    
    
    @implementation UserModel
    
    
    - (void)setDog:(DogModel *)dog{
         _Dog = dog;  
    }
    
    -(DogModel*)Dog{
        return _Dog;
    }
    
    -(void)dealloc{
        NSLog(@"UserModel = (%@)dealloc method.",self.UserName);
        [_Dog release];
        _Dog = nil;
        [super dealloc];
    }
    
    @end

    ************************************************************
    /***   调用代码 ***/
    ************************************************************
    UserModel *user = [[UserModel alloc]init];
    user.UserName = @"struggle";
        
    DogModel *dog=[[DogModel alloc]init];
    dog.dogName=@"小黑";
        
    user.Dog=dog;
        
    [dog release];
    dog=nil;
    
    [user.Dog doing];    
    [user release];
    user = nil;

抛出异常

Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
经过调试发现是野指针的问题,主要是下面两段代码出的问题。

/***   调用代码 ***/
UserModel *user = [[UserModel alloc]init];
user.UserName = @"struggle";
DogModel *dog=[[DogModel alloc]init];  //dog retainCount == 1
dog.dogName=@"小黑";                   
user.Dog=dog;    //user.Dog retainCount == 1    
[dog release];   //user.Dog、dog retainCount == 1
dog=nil;
[user.Dog doing];
/***   UserModel.m ***/
- (void)setDog:(DogModel *)dog{
     _Dog = dog;  
}

当创建一个新的DogModel的实例变量 dog直接赋值给了user.Dog其真正目的只是给了user.Dog一个指针,user.Dog跟dog对应的内存空间是一样的。并且retainCount的值时1,当[dog release]后,retainCount = 0,这个对象也就释放掉了,而user.Dog实际上已经是一个野指针了。

解决方案
/***   UserModel.m ***/
- (void)setDog:(DogModel *)dog{
     if(_Dog != dog){
        [_Dog release];
        _Dog = [dog retain];
     }
}

这个方法,跟property中的(retain)是一样的

你可能感兴趣的:(iOSMRC手动释放对象野指针问题)