黑马程序员-内存管理
一. 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;
当出现两个类相互引用时,一定要有一个类使用assign,表示弱引用,如果都使用retain则会出现相互引用!!
转载于:https://blog.51cto.com/9143994/1556786