黑马程序员-----oc语言学习笔记之内存管理一

来源:互联网 发布:网络pos刷卡平台 编辑:程序博客网 时间:2024/05/05 04:11

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

OC语言内存管理一

1.内存管理的意义
由于移动设备的内存极其有限,所以每个app的内存也是有限制的,当app所占用的内存较多时候,
系统会发出内存警告,1个app可用内存是被限制的,如果一个app使用内存超过20兆,系统发送
warning消息,回收一些内存。
2.oc内存管理的范围
管理任何继承NSobject的对象,对其他的基本数据类型无效


一.内存管理的原理
1)、对象的所有权及引用计数
对象的所有权
任何对象都可能拥有一个或者多个所有者,只要一个对象至少拥有一个所有者,它就会继续存在
2)对象的引用计数器
每个oc对象都有自己的引用计数器,是一个整数表示对象被引用的次数,即现在有多少东
西在使用这个对象,对象刚被创建时候,默认计数器值为1,当计数器的值变为0时候,对象销毁。
3)引用计数器的作用
判断对象要不要回收的依据,计数器为0则销毁,不为0则存在
4)对引用计数器的操作
给对象发消息,retain消息,计数器+1,该方法返回对象本身
release消息,使计数器-1
retainCount消息,获得当前计数器值
5)对象的销毁
当一个对象的引用计数器为0时,那么它将被销毁,占用的内存被系统回收
当对象被销毁时候,系统会向对象发送一条dealloc消息,
在这里释放相关资源,dealloc就像是对象的遗言
一旦对象被回收了,那么他所占据的存储空间就不可能再利用,坚持使用会导致程序崩溃

二、内存管理的原则
1、只要有人在使用某个对象,那么这个对象就不会被回收
   只要你想使用这个对象,那么就应该让这个对象的引用计数器+1
   当你不想使用这个对象,就应该让对象的引用计数器-1
2、谁创建谁release
   如果你通过alloc,new,copy来创建一个对象,那么你就必须调用release或者autorelease方法
   不是你创建的不用你去负责
3、谁retain谁release
   只要你调用了retain,无论这个对象时如何生成,你都要调用release

三、野指针问题
1、单个对象的野指针问题
僵尸对象

#import<Foundation/foundation.h>@interface Person: NSObject@propery int age;@end@implementation Person@endint main(){//创建对象,引用计数器为1//通过引用计数器可以判断对象是否需要回收//使用alloc init方式创建,retainCount =1Person *p=[[Person alloc] init];NSlog(@"p->retainCount = %ld",p.retainCount);[p release]; //release 后 retainCount=0,释放对象空间[p setAge:20];//这个时候p是一个野指针,不能使用,为了避免使用僵尸对象,p=nil,可以防止调用僵尸对象}对象内存泄漏int main(){//创建对象,引用计数器为1//通过引用计数器可以判断对象是否需要回收//使用alloc init方式创建,retainCount =1Person *p=[[Person alloc] init];NSlog(@"p->retainCount = %ld",p.retainCount);[p retain];[p retain];[p release]; //retainCount =2 内存没有释放 泄漏 }
对象使用过程中被赋值nil 导致内存泄漏

int main(){//创建对象,引用计数器为1//通过引用计数器可以判断对象是否需要回收//使用alloc init方式创建,retainCount =1Person *p=[[Person alloc] init];NSlog(@"p->retainCount = %ld",p.retainCount);p=nil; [p release]; //设置对象为nil,实际上让p指向一个特殊地址}
在函数或者方法中使用retain或者relase不当,造成的问题
- (void)compare:(Person*)person{[person retain];NSlog(@"车在猛跑");}Person *p =[[Person alloc]init];NSlog(@"p->retainCount = %ld",p.retainCount);[p comper:p];//调用后retain操作+1[p retain];//此时的对象没有被收回,因为引用计数器没有为0导致内存泄漏
2、多对象野指针问题
#import <Foundation/Foundation.h>@interface Car : NSObject-(void)run;@end@implementation Car-(void)dealloc{NSLog(@"Car被销毁");[super dealloc];}-(void)run{NSLog(@"车正在跑");}@end@interface Person : NSObject{Car *_car;}-(void)setCar:(Car*)car;-(Car*)car;-(void)driver;@end@implementation Person-(void)dealloc{NSLog(@"Person被销毁");[super dealloc];}-(void)setCar:(Car*)car{_car = car;}-(Car*)car{return _car;}-(void)driver{NSLog(@"开车去拉萨!");[_car run];}@end
第一种野指针错误
Person *p [Person new];
Car *car = [Car new];
//给一辆车
[p setCar:car];
//车销毁了
[car release];
//人驾车继续走
[p dirver]; //因为车销毁了 所以产生野指针错误
[p release]; //人对象销毁

解决方法:

-(void)setCar:(Car*)car{__car = [car retain];}
第二种内存泄漏

[p driver];
[p release];
人销毁后,车没有销毁 造成内存泄漏
解决办法:

-(void)dealloc{NSLog(@"Person被销毁");[_car release];//在人的dealloc方法里做减引用计数器的操作[super dealloc];}
第三种内存泄漏
双car对象交换时产生的内存泄漏
Person *person =[[Person alloc]init];
Car *car1 =[[Car alloc]init];
[person setCar:car1];
[person driver];
[car1 release]; //car1 的计数器为1
Car *car2 =[[Car alloc]init];
[person setCar:car2];
[car2 release];
[person release]; //这样 car2 被销毁了  car1 没有被 销毁 造成内存泄漏

解决办法:

-(void)setCar:(Car*)car
{[_car release];//先释放上一个对象,(注意第一次是向nil发送release消息)_car = [car retain];}

第四种 内存泄漏

Person *person =[[Person alloc]init];
Car *car1 =[[Car alloc]init];
[person setCar:car1];
[person driver];
[car1 release];
[person setCar:car1];
[person setCar:car1]; //重复给person 这样就会造成引用计数器增加最后导致car不能被释放,导致内存泄漏

解决办法:

-(void)setCar:(Car*)car{//判断_car 存放的是否是 形参对象,如果不是,则执行[_car realease];if (_car!=car) {[_car release];//先释放上一个对象,(注意第一次是向nil发送release消息)_car = [car retain];}

0 0
原创粉丝点击