黑马程序员————内存管理

来源:互联网 发布:新浪短网址api java 编辑:程序博客网 时间:2024/06/06 07:36

 如果一个APP使用的内存超过20M系统会发送Memory Warning消息 ,之后会回收一些不使用的内存空间


OC内存管理范围

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


BSS段 数据区 代码段  程序启动时候加载

栈区 到代码区是从高地址到低地址

堆区是从低到高


对象所有权

任何对象都可能有一个或多个所有者,只要一个对象至少还拥有一个所有者,他还会继续存在


Cocoa所有权策略

任何自己创建的对象都归自己所有,可使用名字有alloc 和new 开头或名字中包含copy的方法创建对象

使用retain获得一个对象的所有权


对象的引用计数

表示对象被引用的次数,使用这个对象的个数,刚创建对象时,引用计数为1,为0时被销毁。

retainCount 8个字节存储空间存储引用计数 无符号long类型


引用计数器的作用

判断对象是否回收的依据(对象值为nil时引用计数为0但不回收)


retain消息 使引用计数+1

release消息 使引用计数 -1

retainCount消息 获得对象当前的引用计数


当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般重写dealloc方法

若重写dealloc方法就必须调用[super dealloc],并且在代码块的最后调用


对象被收回那么他所占据的存储空间不再可用,坚持使用会导致程序崩溃


如果对象的引用计数不为0那么他占用的内存就不可被回收

任何对象刚创建引用计数为1。


OC内存管理分类

OC提供三种方式


MRC手动管理 手动 retain release autorelease

ARC自动引用计数

garbage collection 垃圾回收 iOS不支持垃圾回收 


MRC与ARC的区别


点击项目 点击 build settings  levels 然后在搜索框输入auto

OC Automatic Reference Counting 点NO就为 MRC


重写dealloc先释放子对象,再释放父类



内存管理的原则

如果你通过alloc new copy创建了一个对象。那么你就必须调用release或者autorelease方法

不是你创建的就不用你去负责


谁retain ,谁release


内存管理研究的内容

野指针:1定义的指针变量没有初始化2指向的空间被释放了


内存泄露

指向堆区的指针释放了,而堆区空间没有释放,堆区的空间就被泄露了



每个Target创建完成后默认为ARC模式

单个对象的野指针问题

检测僵尸对象

选中 停止按钮右边的target---edit----- scheme ------- runDebug------- Diagnostics------Enable Zombie Ojects

如果一个对象被释放了 这个对象就被成为僵尸对象


nil与null的区别

nil是一个对象 Nil类对象

NULL是一个通用指针

[NSNull null]是一个对象,他用在不能使用nil 的场合


如果对象为僵尸对象就不能 retain 了 不能复生 会报错(野指针操作)


避免使用僵尸对象的方法


给nil发送任何消息都没有效果


 set方法存在问题 

原对象无法释放造成泄露


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

if(_car!=car){

[_car release];

_car=[car retain];

}

}

set方法的内存管理

原则:如果一个类中有其他类的对象set方法书写的时候要判断是否是同一个对象,release旧值retain新值


@property 4.4前 

@property+手动实现

@prorerty @synthesize

  

@property (参数1,参数2) 数据类型 方法名

原子性  没做完别人不能打扰

atomic 对属性加锁,多线程下线程安全,默认值

nonatomic 对属性不加锁,多线程下不安全,但是速度快

读写属性

readwrite生成setter,getter,默认值

readonly只生成getter方法

set方法处理

assign直接赋值,默认值

retain先release原来的值,再retain新值

copy先release原来的值,再copy新值


@property(nonatomic,assign)Car *car;


set和get方法的名称

修改set和get方法的名称,主要用于布尔类型,因为放回布尔类型的方法名一般以is开头。

修改名称一般用在布尔类型中的getter

@property(nonatomic,assign,setter=abc:,getter=haha)int age

@property(nonatomic,assign,setter=setVip:,getter=isVip)int vip;


@class 的使用

可以简单地引用一个类

@class Dog;

仅仅是告诉编译器Dog是一个类并不会包含Dog这个类的所有内容


具体使用

在.h文件中使用@class 引用一个类

在.m文件中使用#import包含这个类的.h文件



#import 引入的文件如果发生变化,则所有引用的文件都要重新编译一次

@可以解决循环引入的问题


循环retain 的使用会导致两个对象都会内存泄露

防治方法:让某个对象多释放一次 注意顺序

推荐方法,一端使用assign 一端使用retain


Dog.h

@class Person

@interface Dog:NSObject

@property(nonatomic,retain)Person *owner;

@end


NSString类的内存管理问题

字符串的常量池

如果你需要的字符串在常量池中已经存在了,不会分配内存空间

NSString *str1=@"abc";

NSString  *str3=[NSString stringWithString:@"abc"];

NSString  *str5=[[NSString alloc]initWithString:@"abc"];

这三个都分配到常量区 地址都一样

NSString  *str2=[NSString stringWithFormat:@"aaa"];  在堆区 

NSString  *str4=[[NSString alloc]initWithFormat:@"aaa"];在堆区



常量区的对象引用计数为无符号最大值


在iOS程序运行工程中,会创建无数个池子,这些池子都是以栈结构存在的。

当一个对象调用,autorelease时,会将这个对象放到位于栈顶的释放池中


自动释放池的创建方式

 5.0以前

NSAutoreleasePool * pool=[[NSAutoreleasePool alloc] init];

以后

#autoreleasepool

{


}

autorelease

是一种支持引用计数的内存管理方式

它可以暂时保存某个对象,然后在内存池自己的排干(drain)的时候

对其中的每个对象发送release消息

注意,这里只是发送release消息,如果当时的引用计数依然不为0,则对该对象依然

不会被释放。可以用该方法来保存某个对象,也要注意保存之后要释放该对象。


autorelease的设计确保对象技能正确释放,又能返回有效的对象。

好处不用关心对象释放的时间

不需要在关心什么时候调用release


基 的本用法

会将对象放到一个自动释放池中

挡自动释放池被销毁时,会对池子里的所有对象做一次release

会返回对象本身

调用完autorelease方法后,对象的 计数器不受影响


原理:当池被释放时,该池中的所有对象才会被调用release



autorelease何时释放

对于autorelease本身

1.手动释放autorelease pool

2.Runloop结束之后自动释放

对于池中的内部对象

在引用计数的retain为0时释放,release和autorelease pool的drain都会触发retain事件






































0 0
原创粉丝点击