首页 > 代码库 > 黑马程序员-1.内存管理
黑马程序员-1.内存管理
一. 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;
当出现两个类相互引用时,一定要有一个类使用
retain
黑马程序员-1.内存管理