黑马程序员_IOS内存管理学习总结(一)

------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!


一.为什么要管理内存

1.移动设备的内存很有限,每个app所能占用的内存是由限制的。

2.当app所占用的内存较多时,系统会发出内存警告,这时得回收一些不需要再使用的内存。

3.手动管理内存:
在ios5之后Xcode增加了ARC这个编译器特性,它会自动帮我们生成管理内存的代码。
因为我们以下讨论的内存管理,是在非ARC机制下的手动管理内存,所以需要关闭ARC:
Build Settings —>Apple LLVM 6.0-Language -Objective C —>Objective -C Automatic Reference Counting。选择no。

4.管理范围
 1>对任何继承自NSObject的对象的内存都需要管理,根本原因是对象存放在堆空间中,堆空间的东西是动态分配的,系统不会自动回收,需要通过程序员手动控制释放对象占用的内存。
 2>其他基本数据类型(in、char、float、double、struct、enum等)数据会存放在栈中。栈空间存储的东西系统会自动回收的,无需程序员管理。


二.引用计数器

1.介绍
 1>每个OC对象都有自己的引用计数器,是一个整数。

 2>每个对象的引用计数器用于表示该对象被引用的次数,即由多少人正在使用这个OC对象。

 3>每个OC对象内部专门有4个字节的存储空间来存储引用计数器。

 4>当使用alloc、new或者copy创建一个新对象时,新对象的引用计数器值默认是1。

2.作用
 1>系统根据对象中引用计数器的数值,来判断是否回收该对象占用内存。

 2>程序员通过操作对象的引用计数器,来控制对象被销毁的时机。

3.操作引用计数器
 1>给对象发送一条retain消息,可以使该对象引用计数器值+1。

 2>给对象发送一条release消息,可以使该对象引用计数器值-1。

 3>给对象发送retainCount消息获得该对象的引用计数器值。


三.对象的销毁

1.对象何时被销毁
 1>程序运行过程中,当系统检测到OC对象的引用计数器值为0时,系统就会回收对象占用的内存。

 2>如果对象的计数器始终不为0,那么整个程序运行过程中,它占用的内存就不可能被回收,除非整个程序已经退出(IOS程序运行时main函数是死循环的,如果不回收对象,对象就会一直占用内存)。

2.销毁对象细节
 1>当一个对象被销毁时,系统会自动向对象发送一条dealloc消息。

 2>- (void)dealloc方法是继承自NSObject的对象方法,所以每个OC对象都有该方法。

 3>通常我们会重写对象的dealloc方法,在这里释放相关资源,dealloc就像对象的遗言。

 4>重写dealloc方法时,必须在最后面调用父类的dealloc方法([super dealloc])。

 程序示例 1:

// 重写dealloc方法
- (void)dealloc
{
    // 在[super dealloc]之前释放相关内存
    // 也可以写一些打印提示语句
    NSLog(@"某某对象被销毁了");
    
    [super dealloc]; // 必须在最后调用父类的dealloc方法
}


四.野指针和空指针


1.僵尸对象
 1>所占用内存已经被回收的对象称为僵尸对象。僵尸对象是不能再被使用。

 2>开启僵尸对象检测:
 默认情况下,Xcode是不会检测僵尸对象的,使用一块被释放的内存也不回报错。为了方便测试,应该开启僵尸对象检测。Edit Scheme —>Diagnostics—>Enable Zombie Objects

 3>经典错误: message sent to deallocated instance 给已经释放的对象发送消息。

 程序示例 2:

int main() 
{
    Person *p = [[Person alloc] init]; 
    
    [p release]; // 对象p内存被回收
    
    p.name = @"jack"; // 程序运行到这里会报错: message sent to deallocated instance
    
    NSLog(@"%@", p.name);
    
    return 0;
}

2.野指针

 1>野指针:(OC中是指)指向僵尸对象(不可用内存)的指针,给野指针发送消息会报错。

 2>野指针错误:
当使用野指针操作一块不可用内存时,运行时会发出错误:EXC_BAD_ACCESS。意思为访问了一块不可用的内存(已经被回收)。我们称这个经典错误为野指针错误。

3.空指针
 1>没有指向任何东西的指针(存储的东西是nil、NULL、0)。

 2>OC中不存在空指针错误,给空指针发送消息不会报错,与Java不同。

 3>可以通过清空指针,来防止野指针错误。

 程序示例 3:

int main() 
{
    Person *p = [[Person alloc] init];
    
    [p release]; // 对象p内存被回收
    
    p = nil; // 通过清空指针,可以防止野指针错误
    
    p.name = @"jack"; // 向空指针发送消息,相当于什么都没有做。程序不会报错
    
    NSLog(@"%@", p.name);
    
    return 0;
}


五.管理内存遵循的原则

1.当我们手动管理内存时,需要遵循一些原则,这些原则使我们管理内存时逻辑更加清晰,不容易出错。

2..管理原则
我们需要明确责任人,也就是明确谁使用了对象(使用者)。使用者负责对对象的引用计数器进行操作。

 1>谁创建,谁release

如果你通过alloc、new或copy方法来创建一个对象,那么当你不需要该对象时必须向对象发送一条release消息或autorelease消息(之后会详细介绍)。

程序示例 4:

int main()
{
    Person *p = [[Person alloc] init]; // 程序通过alloc方法创建1个Person对象p
    Person *p1 = [Person new]; // 程序通过new方法创建1个Person对象p1
    
    p.name = @"jack"; // 为p的name属性赋值
    
    NSLog(@"%@", p.name); // 打印p的name属性
    
    [p release]; // 当我们不再使用对象了,要对p做1次release操作。总之要有一个release与之前的alloc对应否则就会造成内存泄露
    p = nil; // 再严谨一些,我们可以清空指针,防止野指针错误
    
    [p1 release]; // 也同样要对p1做一次release操作
    p1 = nil;
    
    return 0;
}

  2>谁要用,谁retain —>谁retain,谁release (例外循环retain)
谁想引用某个对象,谁就向对象发送一条retain消息(引用计数器+1)。谁不再用某个对象时,谁就向该对象发送一条release消息(引用计数器-1)。

 3>只要还有人用某个对象,那么这个对象就不会被回收。

 4>有始有终,有加必有减。
当你对一个对象进行了一次retain操作,必然还要对该对象进行一次release操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值