OC内存管理
1.管理范围:管理任何继承NSObject对象,对其他的基本数据类型无效。
2.内存泄漏:对象和其他数据类型在系统中的存储空间不一样,其他局部变量主要存放于栈中,而对象存储于堆中,当代码块结束时 这个代码块中涉及的所有局部变量会被回收,指向对象的指针也会被回收,此时对象已经没有指针指向了,但仍然存在于内存 中,造成内存的泄漏。
3.引用计数器:
1).用来保存当前对象有几个东西在使用它(整数)
2).引用计数器是判断对象要不要回收的依据(存在一种例外:对象值为nil时,引用计数为0,但不回收空间)就是计数器是否为0, 若不为0则存在.
3).对引用计数器操作:
给对象发送消息,进行相应的计数操作
retain消息:计数器+1,该方法返回对象本身
release消息:是计数器-1(并不代表释放对象)
retainCount消息:获得对象当前的引用计数值
4.对象的销毁:
当一个对象的引用计数器为0时,该对象会被销毁,占用的内存系统会被回收。对象在被销毁时,系统会自动向对象发送一条dealloc消息,一般会从写dealloc方法,在这里释放相关的资源,重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法),一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)。
5.注意:
1).对象计数器不为0,存储空间则不会被回收
2).对象一旦创建好,它的引用计数器默认为1,
6.MRC手动内存管理
ARC自动内存管理
注意:创建一个项目,默认的是ARC(自动内存管理)
把ARC自动内存管理换成MRC手动内存管理步骤:
一.手动内存管理
1.如果想使用这个对象就应该让引用计数器加1,以免空间被回收,如果不想用就让引用计数器为0,释放空间,防止造成内存泄 漏,也就是谁创建的谁release,谁retain谁release。
2.手动内存管理例子:
注意:对象被释放后不能访问它的引用计数器,如果访问的话是野指针访问会造成系统崩溃。
3.重写dealloc方法
1).对象被销毁的时候,会默认调用dealloc方法
2).dealloc方法书写规范,要先释放自己的对象空间,在释放父类的空间
3).注意:dealloc方法不用手动去调用,系统会根据引用计数器的值自动调用
二.单个对象的内存管理(野指针)
1.如果一个对象被释放了,则该对象被称为僵尸对象,僵尸对象不能再使用。
2.野指针就是访问了一块不存在的内存
3.Xcode在默认的情况下在使用僵尸对象是不会报错的,如果想报错的情况下要打开僵尸对象的检测,但一般为提高效率,是不会时时打开僵尸对象检测的。
4.空指针:没有指向任何空间的指针,给空指针发送消息不会报错
nil:给nil发送任何消息,都没有效果
Nil:类对象
NULL:通用指针(泛型指针)
[NSNull null]是一个对象,他用在不能使用nil的场合。
5.为避免僵尸对象的使用报错的方法是对象在释放以后,给对象赋值为nil
6.单个对象的内存泄漏问题
1).创建完成之后没有release
例:Dog *d=[ [Dog alloc] init ];
NSLog(@"%lu",d.retainCount);
引用计数器为1,没有release
2).不当的使用nil
例:Dog *d=[ [Dog alloc] init ];
d=nil;nil赋值给d,实际上是让的指向一个无效的地址
[d release];相当于让nil 发送release消息,引用计数器不会-1,值为nil的对象retainCount=0
3).在方法中不当的使用retain 和relaese
例:-(void) test:(Dog *)dog{
//在方法内部修改引用计数器
[ Dog retain];
}
在main.m里调用
Dog *d=[ [Dog alloc] init ];
[ d test : d];
[ d release];
注意:此时没有释放空间,应为引用计数器在方法里已经修改了