内存管理

iOS开发中,对堆内存的创建、销毁(释放),就叫做内存管理。

内存管理有两种方式:

MRC:手动内存管理。

ARC:自动内存管理。


一,

内存管理的机制:

每个对象都有自己的引用计数器。在MRC内存管理模式下,引用计数器计算机是无法自动操作的。

向对象发送[对象 retainCount];该对象引用计数器的值

当向对象发送alloc、copy、new消息的时候,该对象的引用计数器会自动设置为1.

当不再使用对象的时候的时候,会发送release消息,通知引用计数器”减”1。

当一个对象的引用计数器的值为0时,”系统”会”自动”销毁该对象,并回收该内存空间。

当对象销毁的时候,会”自动”发送dealloc消息。

//重写父类的dealloc方法
- (void)dealloc{
    NSLog(@"对象销毁了");
    [super dealloc];
}



二,在xcode5以后,都是强制使用ARC内存管理的。

需要手动改成MRC内存管理:

项目->BuildSetting->All->ARC->OC language->OC ARC=NO;

强制操作系统立刻回收内存:

edit scheme->Diag…->Enable Zombie Objects

三:

引用计数器:用来记录对象被引用的次数,每个对象天生就有一个引用计数器。

Reference Counting

引用的次数:一个对象被几个引用使用。

@autoreleasepool {
        //分配了一个堆空间
        TRStudent *stu = [[TRStudent alloc]init];
        TRStudent *stu2 = stu;
        //查看该对象的引用计数器
        NSUInteger count = [stu retainCount];
        NSLog(@"count:%lu",count);
        [stu study];
        NSLog(@"stu:%p stu2:%p",stu,stu2);
        //释放堆空间
        [stu release];//free()
        //[stu2 study];
    }
 

TRStudent *stu = [[TRStudent alloc]init];
TRStudent *stu2 = stu;

内存管理使用不当:通过引用使用一个以经不存在的对象(堆空间),会出现异常、crash(Exception)。

解决:1.野指针问题,使用空指针来解决野指针问题。

对象不在使用的时候,忘记发送release消息,内存溢出(内存浪费)(内存泄露)。

四:

解决:1.谁创建的内存(谁加1),谁就有责任减1。

@autoreleasepool {
        //RC:1
        TRStudent *stu = [TRStudentnew];
        //两个引用共用一个对象
        TRStudent *stu2 = stu;
        //通知引用计数器加1
        [stu2  retain];
        NSUInteger count = [sturetainCount];
        NSLog(@"count:%lu",count);
        [stu2  study];
        //谁通知引用计数器加1谁有责任做减1操作
        [stu release];//RC:2-1 = 1
        [stu2  study];
        [stu2  release];//RC:1-1 = 0
    }



五:对象当中有属性为对象:   

#import <Foundation/Foundation.h>
#import "TRBook.h"
@interface TRStudent :NSObject
//本质属性
//1.书的实例变量
{
    TRBook *_book;
}
//2.setter/getter book
-(void)setBook:(TRBook*)book;
-(TRBook*)book;

-(void)study;
@end



六:声明式属性解决加1操作,但减1操作依然需要手动处理。(也就是对象当中有属性为对象:这种的方式内存管理可以写为下面这种形式)

@implementation TRStudent
/*
-(void)setBook:(TRBook*)book{
    //第二种情况多次读书的问题
    if (_book==nil) {//第一次读书
        _book = book;
        [_book retain];
    }else{
        [_book release];
        _book = book;
        [_book retain];
    }
    
    // 第一种情况属性如果是对象类型存在内存隐患
    //_book = book;//真正赋值的时候在这里
    //[_book retain];//有责任做加1操作
     
}
-(TRBook*)book{
    return _book;
}
*/
-(void)study{
    NSLog(@"学生具有学习的能力看书 book:%d",self.book.price);
}
//重写
- (void)dealloc{
    [_bookrelease];//当不再使用书的时候,有责任减1
    NSLog(@"Student对象销毁了");
    [superdealloc];
}


七:自动释放池是OC的一种内存自动回收机制,可以将一些临时变量通过自动释放池来

回收

统一释放

  自动释放池本事销毁的时候,池子里面所有的对象都会做一次release操作



@autoreleasepool {//开始
        TRStudent *stu = [[[TRStudentalloc]init]autorelease];
        //[stu ...];
        //[stu autorelease];
        /*
        TRStudent *stu = [TRStudent student];
        NSObject *obj = [stu obj];
         */
        NSLog(@"自动释放池末尾");
    }//结束当自动释放池结束的时候,会向池中的对象发送release消息
    NSLog(@"程序的末尾");
    return0;