首页 > 代码库 > 黑马程序员-1.内存管理

黑马程序员-1.内存管理

一. 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;

当出现两个类相互引用时,一定要有一个类使用

retain


黑马程序员-1.内存管理