iPhone开发内存管理

开发iPhone 应用程序并不难,基本上就是三个词 - “memory, memory, memory” 。iPhone OS 对内存的要求很严格,有memory leak ,杀掉; 内存使用超限额,杀掉。一个通过测试的程序,在使用过程当中90%以上的崩溃都是内存问题形成的。在这里简单总结一下Object-C 内存管理。
  基本概念
  Object-C 的内存管理基于引用计数(Reference Count)这种很是经常使用的技术。简单讲,若是要使用一个对象,并但愿确保在使用期间对象不被释放,须要经过函数调用来取得“全部权”,使用结束后再调用函数释放“全部权”。“全部权”的得到和释放,对应引用计数的增长和减小,为正数时表明对象还有引用,为零时表明能够释放。
  函数
  得到全部权的函数包括
  alloc - 建立对象是调用alloc,为对象分配内存,对象引用计数加一。
  copy - 拷贝一个对象,返回新对象,引用计数加一。
  retain - 引用计数加一,得到对象的全部权。
  另外,名字中带有alloc, copy, retain 字串的函数也都认为会为引用计数加一。
  释放全部权的函数包括
  release - 引用计数减一,释放全部权。若是引用计数减到零,对象会被释放。
  autorelease - 在将来某个时机释放。下面具体解释。
  autorelease
  在某些状况下,并不想取得全部权,又不但愿对象被释放。例如在一个函数中生成了一个新对象并返回,函数自己并不但愿取得全部权,由于取得后再没有机会释放(除非创造出新的调用规则,而调用规则是一切混乱的开始),又不可能在函数内释放,能够借助autorelease 。所谓autorelease , 能够理解为把全部权交给一个外在的系统(这个系统实际上叫autorelease pool),由它来管理该对象的释放。一般认为交给 autorelease 的对象在当前event loop 中都是有效的。也能够本身建立NSAutoreleasePool 来控制autorelease的过程。
  据苹果的人说,autorelease效率不高,因此能本身release的地方,尽可能本身release,不要随便交给autorelease来处理。
  规则
  引用计数系统有本身的引用规则,遵照规则就能够少出错:
  得到全部权的函数要和释放全部权的函数一一对应。
  保证只有带alloc, copy, retain 字串的函数才会让调用者得到全部权,也就是引用计数加一。
  在对象的 dealloc函数中释放对象所拥有的实例变量。


iPhone 开发过程当中,内存的使用相当重要。不但要合理分配使用内存,还要注意内存泄露的问题, 由于内存泄露会致使程序因为内存不足而崩溃。根据我的开发的经验来看,在开发iPhone程序的过程当中,关于内存的问题须要注意如下几点:
  内存分配、释放成对出现
  使用 alloc 分配的内存对象须要在用完后 调用release释放
  注意copy,retain,assign操做符的区别
  copy, retain操做符赋值的对象和alloc同样,须要release释放,不然会致使内存泄露
  assign 操做符的含义是将对象指向另外一对象, 二者指向的是同一内存对象,无需调用release释放
  NSArray, NSDictionary, NSMutableArray, NSMutableDictionary等容器类, 在使用这些容器类的时候要注意, 在添加对象到这些类对象时,容器类会自动调用一次retain,好比
  NSString* string = [[NSString alloc] initWithString:@”test string”]; // refCount = 1
  NSArray* array = [NSArray array];
  [array addObject:string]; // refCount = 2
  [string release]; // refCount = 1
  这种状况, 即使string已经调用release,可是在加入 array中时已经调用了一次retain,注意refCount的变化 简单介绍一下iPhone 或者说Objective C对对象的管理机制。 OC中采用一种引用计数refCount的方式来管理内存对象,当refCount等于0的时候就会释放对象所占的内存, 操做符alloc,copy, retain都会将refCount加1表示引用计数增长, 而调用release使 refCount自动减1, 当refCount=0时表示该对象已经没有被引用,能够将其释放, 以后该对象便不可用
  连续重复分配内存的过程最好建立本身的自动释放池 NSAutoreleasePool,一般是在for、while等循环操做过程当中,好比
  for( int i=0; i < 100; i++ )
  {
  NSString* str = [[NSString alloc] initWithString:@”some string”];
  // 针对str的操做
  [str release];
  }
  在这种状况下,有2点须要注意,首先若是可能,就把str的分配、释放放在for循环外面, 从而减小内存的分配、释放致使程序效率低下,也利于内存回收,如上例应该为
  NSString* str = [[NSString alloc] initWithString:@”some string”];
  for( int i=0; i < 100; i++ )
{
  // 针对str的操做
  }
  [str release];
  若是实际状况复杂,不能像例子中那样抽离出循环外,须要建立本身的内存管理池, 一样适用于须要大量autorelease对象的过程
  NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
  for(int i=0; i < 100; i++ )
  {
  // actions
  }
  [pool release];
  之因此要这样作,是由于apple处理iPhone的内存管理机制问题, 一般状况下,系统会在须要的时候释放整理全部的autorelease对象,这就是为何有时候autorelease对象在做用域范围外还有多是有效的
  避免不经常使用对象驻留内存, 桌面开发的tx不少喜欢在程序初始化的时候将某些资源好比小图片加载进内存,从而提升程序运行效率。 但这种方式在iPhone以及其它mobile移动设备开发时须要避免,由于对于这些设备来讲,内存永远显得不足(固然普通pc内存也是越大越好:) )。 按照apple的官方说法, Load resources lazily . 就是在须要的时候再从硬盘上读取,而避免常驻内存。
相关文章
相关标签/搜索