码迷,mamicode.com
首页 > 其他好文 > 详细

Objective-C 内存管理

时间:2015-04-17 13:36:58      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:

今天我们简单的对内存管理有个简单的认识,首先我们要提出的疑问就是为什么要使用内存管理,举个例子吧,我们在使用iPhone手机应用的时候,经常会出现以下闪退的应用,或者下载下来就Crash的,90%以上的原因都是因为内存的管理问题,仅凭这一点就值得我们重视内存管理.但是在一个拥有数十个甚至上百个的工程里,查找内存问题是极其困难的, 我们学习了解内存,以及内存会常见的问题,就能够帮助我们减少出错几率.

内存问题体现在两个方面: 内存溢出 , 野指针异常

内存溢出:iOS给每个应用程序提供了一定的内存,用于程序的运行. iPhone 3GS内存30M左右,iPhone 5S 内存80M左右,一旦超出内存上限,程序就会Crash. 程序中最占内存的就是图片,音频,视频等资源文件.3.5寸非Retina屏幕(320*480)放一张全屏图片,占用字节数320*480*4(一个像素占4个字节,存放RGBA),即:600k Bytes. iPhone 3GS同时读取60张图片就会crash. 4寸屏幕(320*568),实际像素640*1136,程序存放一张全屏图片,占用字节数640*1136*4,即2.77M Bytes.iPhone 5S同时读取40张图片就会crash.

野指针异常:对象内存空间已经被系统回收,仍然使用指针操作这块内存,野指针异常是程序crash的主要原因,代码量越来越大的程序,就会越来越难找出野指针的位置. 把内存管理学习好,能够帮助我们提升程序的性能,也可以大大减少调试Bug的时间.

内存管理的方式:包含垃圾回收(gc),MRC(Manual Reference Count),ARC(Auto Reference Count).

1. 垃圾回收:程序员只需要开辟内存空间,不需要用代码释放,系统来判断不被使用的空间,然后回收这些内存空间,然后进行内存分配. 整个回收的过程不需要写任何代码,由系统自动完成垃圾回收.

2. MRC: 人工引用计数:内存的开辟和释放都由代码进行控制,相对垃圾回收来说,对内存的控制的更加灵活,可以在需要释放的时候及时释放,对程序员的要求较高,程序员要熟悉内存管理的机制,要遵守一个内存的黄金法则, 谁开辟了空间,就要谁释放,也就是只要有alloc init,那么就要对开辟的空间进行释放.

3.ARC:自动引用计数:iOS 5.0的编译器特性,它允许用户只开辟空间,不用去释放空间,它和垃圾回收机制不一样,它的本质还是MRC,只是编译器帮程序员默认加了释放的代码,后续在iOS开发阶段的时候,可以更深刻的了解这一点.

iOS支持两种内存管理方式:ARC和MRC, MRC的内存管理机制是引用计数,ARC是基于MRC的. 关于引用计数,我们在一一做介绍. 这些都是我们以后会经常遇到的,希望大家不要觉得烦闷,认为这东西太概念化,能不能处理好内存管理对你的应用有直接的关系. 因为代码都是大同小异,但是优化内存是一个细心出慢活的任务.

引用计数:在C语言中,我们都使用过malloc和free,进行堆内存的创建和释放,堆内存只有正在使用和销毁两种状态, 在实际开发中,可能会遇到,两个以上的指针使用同一块内存,C语言无法记录内存使用者的个数. 但OC的引用计数机制管理内存,当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减,当引用计数到零时,该对象就讲释放占有的资源, 好好理解一下这段话.

影响引用计数的方法:+alloc -retain -copy -release -autorelease

+allco:开辟内存空间,如果还不知道alloc是干嘛的,那就赶紧回家放羊去吧. 给创建的对象开辟内存空间,这时候他的引用计数变为1,这是从0到1的过程.

-retain:引用计数加1,如果内存空间之前引用计数为1,那么retain之后就会变为2,如果引用计数是5,retain之后就会变成6. 字面意思很容易理解的,多多操作一下,就会更加深刻.

-copy:把某一内存区域的内容拷贝一份,拷贝到新的内存空间里去,被拷贝的区域的引用计数不变,新的内存区域的引用计数为1. 不要和retain搞混了,一般人的痔疮,对copy和retain会有些混淆. copy和retain不同,一个对象想要copy,生成自己的副本,需要实现NSCopying协议,定义copy细节(如何copy),如果类没有接收NSCopying协议而给对象发送copy消息,会引起crash. 实现方法如下:

Person.h文件

@interface Person:NSObject <NSCopying>

@property (nonatomic,copy)NSString *name;

@property (nonatomic,assign)NSInteger age;

@end

Person.m文件

@implementation Person

- (id)copyWithZone:(NSZone *)zone{

Person *p = [[Person allcoWithZone:zone]init];

p.age = self.age;

p.name = self.name;

return p;

}

main.m文件

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

p.name = @"Jack";

p.age = 20;

Person *p2 = [p copy];

p2是p的副本,p2.name与p.name一样. p2.age与p.age一样.

-release:引用计数减1,如果内存空间之前引用计数为4,release之后变为3,如果引用计数为1,release之后变为0,内存就会被系统回收.

-deallco:是集成父类的方法,当对象引用计数为0的时候,由对象自动调用.我们可以通过代码来验证引用计数是否降为0了. 代码如下:

- (void)dealloc

{

  NSLog(@"%@被销毁了",self);

  [super dealloc];

}

-autorelease:未来的某一时刻引用计数减1. 如果内存之前引用计数为4,autorelease之后仍然为4,未来的某个时刻会变为3.这么说有点太含糊了,不容易理解,我们在详细的解释一下.

要详细了解autorelease,首先我们要先了解autoreleasepool(自动释放池), autorelease对象的释放是由autoreleasepool来控制的. 向一个对象发送autorelease消息,这个对象何时释放,取决于autoreleasepool. 我们用代码来解释一下autoreleasepool的使用:

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

Person *p = [[Person alloc]init];//retainCount为1

[p retain];//retainCount为2

[p autorelease];//retainCount为2  暂时还没有释放,而是在未来的某一时刻释放

[pool release];//此时 autolease的对象引用计数 -1

NSLog(@"%d",[p retainCount]);//打印结果为1

解释:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];和[pool release];就像一对括号,[xxx autorelease];必须写在两者之间. 

[xxx autorelease];出现在了两者之间,pool就会把接受autorelease的对象给保存起来(以栈的方式,把对象压入栈)  当[pool release];的时候,pool会向之前保存的对象一一发送release消息(对象出栈,越晚autorelease的对象,越早接收release消息).

在iOS之后,不再推荐使用NSAutoreleasePool类,而是使用@autoreleasepool{}替代,之前写在NSAutoreleasePool *pool = [[NSautoreleasePool alloc]init];和[pool release];之间的代码,需要写在@autoreleasepool{}大括号里. 出了大括号,自动释放池才向各个对象发送release消息.

内存管理的原则: 引用计数的增加和减少相等,当引用计数将为0之后,不应该在使用这块内存空间.

内存管理黄金法则:凡是使用了alloc,retain或者copy让内存的引用计数增加了,就需要使用release或者autorelease让内存的引用计数减少,在一段代码,增加和减少的次数要相等.

 

这些文字性的东西,看起来会很烦操, 但希望大家可以好好理解一下,因为内存管理是非常重要的,我是重新返工来理解这些概念性的东西. 但我不希望你们和我一样忽视这最不该忽视的.

 

Objective-C 内存管理

标签:

原文地址:http://www.cnblogs.com/why2wm/p/4434538.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!