您的位置:首页 > 其它

09 内存管理初级

2014-11-25 16:31 190 查看
⼀、内存管理的方式
1)简述
1>ios应用程序出现Crash(闪退),90%以上的原因是内存问题,了解内存常见问题,帮助我们减少出错几率。内存问题体现在两个方面:内存溢出,野指针异常

2>野指针异常:对象内存空间已经被系统回收,仍然使用指针操作这块内存。野指针异常是程序crash的主要原因。代码量越大的程序,越难找出现野指针的位置。

野指针->最好安全释放
3>垃圾回收 (gc)

程序员只需要开辟内存空间,不需要⽤代码显⽰地释放,系统来判断哪些空间不再被使用,并回收这些内存空间,以便再次分配。整个回收的过程不需要写任何代码,由系统自动完成垃圾回收。Java开发中一直使用的就是垃圾回收技术
MRC(Manual Reference Count)

人工引⽤计数:内存的开辟和释放都由程序代码进行控制。相对垃圾回收来说,对内存的控制更加灵活,可以在需要释放的时候及时释放,对程序员的要求较高,程序员要熟悉内存管理的机制。

ARC (Auto Reference Count)

自动引用计数:iOS 5.0的编译器特性,它允许用户只开辟空间,不用去释放空间。它不是垃圾回收!它的本质 还是MRC,只是编译器帮程序员默认加了释放的代码。

⼆、引用计数机制,影响计数的各个方法。

1)简述

C语⾔中,使⽤malloc和free,进⾏堆内存的创建和释放。堆内存只有正在使⽤和销毁两种状态。

OC采用引⽤计数机制管理内存,当一个新的引⽤指向对象时,引⽤计数器就递增,当去掉⼀个引⽤时,引⽤计数就递减。当引用计数到零时,该对象就将释放占有的资源。

+alloc :开辟内存空间,让被开辟的内存空间的引用计数变为1。 这是由0到1的过程。
-retain :引用计数加1,如果内存空间之前引用计数为1,ratain之后变为2

-release :引⽤计数减1,如果内存空间之前引用计数为4,release之后变为3
-copy :把某一内存区域的内容拷贝一份,拷⻉到新的内存空间⾥去,被拷⻉区域的引用计数不变,新的内存区域的引⽤计数为1。
-autorelease:未来的某一时刻引用计数减1。如果内存之前引⽤计数为4,autorelease之后仍然为4,未来某个时刻会变为3。(延迟一段时间)

-autoreleasepool :向⼀个对象发送autorelease消息,这个对象何时释放,取决于
autoreleasepool。
2)代码实例

// 1.创建Person对象

// alloc将对象的引用计数器从0到1,从无到有

Person *person1 = [[Person
alloc]init];
// 计数器1

//
改一下这里 Automatic Reference Counting
自动引用为 NO

NSLog(@"%lu",[person1
retainCount]);

// 2.使用新对象再持有一次

// retain:将
对象
的引用计数器 +1

Person *person2 = [person1
retain]; //2

NSLog(@"%lu",[person2
retainCount]);

//不管有没有接收,只要给对象发送retain消息,
对象的引用计数器 +1
[person1
retain]; //3

NSLog(@"%lu",[person2
retainCount]);

// 3.
将引用计数器 -1
[person1
release];

NSLog(@"%lu",[person2
retainCount]);
//针对对象使用的,任何的对象都可以 //2
[person1
release];

NSLog(@"%lu",[person2
retainCount]);//1
[person1
release], person1 =
nil, person2 = nil;
//person1 = nil,安全释放,指针置为nil

NSLog(@"%lu",[person2
retainCount]);//1
内存已经被收回了

// 自动释放池

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

Person *p1 = [[Person
alloc]init];//1
[p1
retain];//2

NSLog(@"%lu",p1.retainCount);

//延迟释放

[p1 autorelease];

NSLog(@"%lu",p1.retainCount);
//2

//销毁自动释放池
[autoreleaselPool
release];

NSLog(@"%lu",p1.retainCount);
//1

//iOS5.0之后,
可以写 @autoreleasepool { }这种语法来表示自动释放

@autoreleasepool {

Person *p2 = [[Person
alloc]init];

NSLog(@"%@",p2);
[p2
autorelease];

Person *p3 = [[Person
alloc]init];

NSLog(@"%@",p3);
[p3
autorelease];
}

三、dealloc⽅法 对象死了属性消失

dealloc是继承自父类的方法,当对象引用计数为0的时候,由对象自动调用。
2)实例代码

- (void)dealloc
{

NSLog(@"%@
被释放了",
self);

//
使用从父类继承过来的方法,销毁从父类继承过来的属性或者实例变量
[super
dealloc];
}

四、内存管理的基本原则。

凡是使⽤了alloc、retain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。在一段代码内,增加和减少的次数要相等。

五、掌握copy的实现。 克隆 互不影响

一个对象想要copy,生成⾃己的副本,需要实现 NSCopying协议,定义copy的细节(如何copy)。如果类没有接受NSCopying协议而给对象发送copy消息,会引起crash。
Person.h文件中

//要想实现对象的拷贝,第一步是在文件.h中遵守<NSCopying>协议

@interface Person :
NSObject<NSCopying>

@property (nonatomic ,
copy) NSString *name;

@property (nonatomic,
assign) NSInteger age;

Person.m文件中

// 2实现<NSCopying>协议中的方法, copyWithZone:
- (id)copyWithZone:(NSZone *)zone
{

//
创建一个和person一模一样的对象返回

Person *p = [[Person
allocWithZone:zone] init];
p.name =
self.name;
p.age =
self.age;

return p;

}
main,m 文件中

Person *p2 = [[Person
alloc]init];
p2.name =
@"大丫头";
p2.age = 19;

Person *p = [p2 copy];

NSLog(@"%@ %ld",p.name,p.age);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: