内存管理简单理解

移动设备的内存极其有限,每个App所占的内存也是有限的,当App占用内存较多时,会有内存警告。如果一个app使用的内存超 过20M,则系统会向该app发送Memory Warning消息。收到此消息后,需要回收一些不需要再 继续使用的内存空间,比如回收一些不再使用的对象和变量等,否则程序会崩溃。 

1.OC的内存管理范围

可以管理任何继承NSObject的对象,对其他的基本数据类型无效。

本质是因为对象和其他数据类型在系统中的存储空间不一样,其他局部变量主要存放在栈中,而对象存放在堆中,当代码块结束时代码块中的所有局部变量都会被回收,指向对象的指针也会被收回,此时的对象没有指针指向,依然存在于内存中,会造成内存泄露。

2. OC内存管理的原理

(1)对象的所有权及引用计数

(2)对象的引用计数器:

每一个OC对象都有自己的引用计数器,是一个整数表示对象被引用的次数,对象刚被创建的时候,默认引用计数器值为1。

用引用计数器是判断对象要不要回收的依据,引用计数器不为0时,则对象存在。

(3)对引用计数器的操作

retain:计数器+1,返回对象本身;

release:计数器-1,但是并不代表对象被释放;

returnCount:当前对象的引用计数

(4)对象的销毁

当对象销毁时,系统会自动向对象发送一条“dealloc”方法,一般是重写这个方法,相当于是“临终遗言”

3. 内存管理分类

MRC、ARC、垃圾回收机制

4. 内存管理原则

(1)只要还有人在使用某个对象,那么这个对象就不会被回收;

    只要你想使用这个对象,那么就应该让这个对象的引用计数器+1;

    当你不想使用这个对象时,应该让对象的引用计数器-1; 

(2)谁创建,谁release

(3)谁retain,谁release

5. 内存问题

(1)内存泄露

<1>在代码块结束之后,当对象的引用计数器值不为0的时候,会造成内存泄露;

<2>retain和release个数不匹配;

<3>对象使用的过程中,被赋值了nil;

(2)野指针

僵尸对象:已经被销毁的对象;为了防止不小心调用了僵尸对象,可以将对象赋值为nil

野指针:指向僵尸对象的指针

空指针:没有指向存储空间的指针(里面存的是nil, 也就是0) ,给空指针发送消息不会报错

6. set方法的内存管理

(1)存在的问题

原对象无法释放造成的内存泄露;

原对象能够释放,但是引起新的问题,set自己的时候,造成的野指针 ;

解决:

(1)判断新传递的对象是否是原来的对象,如果不是原来的对象则释放,然后再retain 

-(void)setCar:(Car*)car{

  //判断_car 存放的是否是 形参对象,如果不是,则执行[_car realease];

  if (_car!=car) { 

  [_car release];//先释放上一个对象,(注意第一次是向nil发送release消息)

   _car = [car retain];

  }

}

(2)对于基本数据类型,直接赋值

-(void)setAge:(int)age
{

  _age=age;

(3)OC对象类型

-(void)setCar:(Car *)car

{
  //1.先判断是不是新传进来的对象

  if(car!=_car) {

  //2 对旧对象做一次release

  [_car release];//若没有旧对象,则没有影响

  //3.对新对象做一次retain
  _car=[car retain]; 

  }  

}

 7. @property参数

(1)

xCode 4.4前:@property帮我们生成get和set方法的声明我们自己实现get和set方法 @property和@synthesize联合@property ;

xCode 4.4后:@property int age; 1)生成一个_age 2)生成get和set方法的声明 3)生成get和set方法的实现;@property (......) int age; 

(2)@property 有两个对应的词,一个是@synthesize,另一个是@dynamic;

如果 @synthesize 和@dynamic 都没写,那么默认的就是@syntheszie var = _var; 

@synthesize 的语义是如果你没有手动实现 setter 方法和 getter 方法,那么编译器 会自动为你加上这两个方法;

@dynamic 告诉编译器:属性的 setter 与 getter 方法由用户自己实现,不自动生 成(当然对于 readonly 的属性只需提供 getter 即可) 

假如一个属性被声明为@dynamic var,然后你没有提供@setter 方法和@getter 方 法,编译的时候没问题,但是当程序运行到 instance.var = someVar,由于缺 setter 方法会导致程序崩溃;或者当运行到 someVar = instance.var 时,由于缺 getter 方 法同样会导致崩溃。编译时没问题,运行时才执行相应的方法,这就是所 谓的动态绑定

(3)参数

参数类别参数说明
原子性atomic对属性加锁,多线程下线程安全,默认值
nonatomic对属性不加锁,多线程下不安全,但是速度快
读写属性readwrite生成getter,setter,默认值
readonly只生成getter方法

set方法处理

assign直接赋值,默认值(适用于非OC对象类型)
retain先release原来的值,再retain新值(适用于OC对象类型)
copy先release原来的值,再copy新值

8. 循环引用问题
场景:比如A对象retain了B对象,B对象retain了A对象 循环retain的弊端 这样会导致A对象和B对象永远无法释放 
解决:当两端互相引用时,应该一端用retain、一端用assign 
9. autorelease基本使用
9.1 自动释放池
(1)在iOS程序运行过程中,会创建无数个池子,这些池子都是以栈结构(先进后出)存在的。
(2)当一个对象调用autorelease时,会将这个对象放到位于栈顶的释放池中 
 9.2 autorelease
(1)如果一个方法需要返回一个新建的对象,该对象何时释放? 方法内部是不会写release来释放对象的,因为这样做会将对象立即释放而返回一个空对象;调用 者也不会主动释放该对象的,因为调用者遵循“谁申请,谁释放”的原则。那么这个时候,就发 生了内存泄露。 
(2)autorelease是一种支持引用计数的内存管理方式;
它可以暂时的保存某个对象(object),然后在内存池自己的排干(drain)的时候对其中的每个 对象发送release消息
注意:这里只是发送release消息,如果当时的引用计数(reference-counted)依然不为0,则该 对象依然不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。
 (3)使用autorelease的好处
不需要再关心对象释放的时间;
需要再关心什么时候调用release。
(4)autorelease的基本原理
autorelease实际上只是把对release的调用延迟了,对于每一个Autorelease,系统只是把该Object放入了当前的Autorelease pool中,当该pool被释放时,该pool中的所有Object会被调用Release。
(5)何时释放 
 对于autorelease pool本身,会在如下两个条件发生时候被释放
1)手动释放Autorelease pool
2)Runloop结束后自动释放
对于autorelease pool内部的对象在引用计数的retainCount == 0的时候释放。release和autorelease pool 的 drain都会触发 retain--事件。 
(6)基本使用
1)会将对象放到一个自动释放池中
2)当自动释放池被销毁时,会对池子里的所有对象做一次release
3)会返回对象本身
4)调用完autorelease方法后,对象的计数器不受影响(销毁时影响) 
(7)注意点
1)并不是放到自动释放池代码中,都会自动加入到自动释放池
2)自动释放池的嵌套使用
3)自动释放池中不适宜放占用内存比较大的对象 
(8)在不手动指定autoreleasepool的前提下,一个autorelease对象什么时候被释放
1)手动干预释放时机--指定autoreleasepool--->就是所谓的:当前作用域大括号结束时释放。
2) 系统自动去释放--不手动指定autoreleasepool--->Autorelease对象出了作用域之后,会被添加到最近一次创建的自动释放池中,并会在当前的 runloop 迭代结束时释放。

 

转载于:https://www.cnblogs.com/gss-blog/p/5846037.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值