首页 > 代码库 > iOS内存管理

iOS内存管理

1.

  ios的内存管理采用的是手动回收机制,每次alloc init / new / copy执行过后,针对某对象的内存计数器将会+1,该对象执行一次release操作则-1。当计数器为0时,则该对象被回收。若计数器当前计数为0,依然执行release的话,程序则会crash。

若变量获取的方法不属于alloc new copy 三者之一,则可认为已被设置为autorelease

 alloc:像某个类发送alloc消息的结果就是给类分配一块足够大的内存来存放实例变量。同时alloc还会顺便将这块内存全部初始化为0.一块刚刚分配的内存不能立即使用,需要先初始化该对象才能使用。

init:是从操作系统取得一块内存,准备用于存储对象。要与alloc嵌套调用,因为初始化方法返回的对象可能与分配的对象不同。

  iPhone没有动态内存交换,如果你在堆中分配了一些动态内存如NSString,即使系统内存不够了,系统也不会将它写到磁盘中来整理出一些内存,取而代之的是一个内存警告。动态内存交换对手持系统来说要求太高,因此没有启用。
  比较系统的一篇IOS内存管理的文章:http://blog.csdn.net/KOmyself/article/details/7549229

  内存中常量字符串的空间分配与其它对象不同,它们没有引用计数机制,因此永远不能释放这些对象,[(retain count)返回0Xffffffff] 

  创建后被多次 多个位置引用的对象(可能存放在一个数组中也可能被其他地方的实例变量引用)只有在确定被引用完之后才能释放占用的内存,Foundation为此提供了一个巧妙的解决方案,用于跟踪对象的引用次数:引用计数。(创建时为1,每次必须保持该对象时发送【myFraction retain】消息,引用次数加1  不再需要时,发送【myFraction release]消息,使对象引用次数减1 retain为0 时 释放内存向对象【发送dealloc消息】)

  对对象添加到任何类型的集合都会使得该对象的引用次数加1,这就是每次addSubview之后都要release一下的原因,该对象不会被释放,仍可被引用。但赋值,拷贝操作 retain大小不变。将对象添加到自动释放池(release),并不影响其引用次数,仅仅为以后释放做了标记。

 

  2.

  assign、retain、copy、atomic、nonatomic之间的区别:

 

转自:http://blog.csdn.net/zcl369369/article/details/7551500

 

1). 假设你用malloc分配了一块内存,并且把它的地址赋值给了指针a,后来你希望指针b也共享这块内存,于是你又把a赋值给(assign)了b。此时a和b指向同一块内存,请问当a不再需要这块内存,能否直接释放它?答案是否定的,因为a并不知道b是否还在使用这块内存,如果a释放了,那么b在使用这块内存的时候会引起程序crash掉。 

2). 了解到1中assign的问题,那么如何解决?最简单的一个方法就是使用引用计数(reference counting),还是上面的那个例子,我们给那块内存设一个引用计数,当内存被分配并且赋值给a时,引用计数是1。当把a赋值给b时引用计数增加到2。这时如果a不再使用这块内存,它只需要把引用计数减1,表明自己不再拥有这块内存。b不再使用这块内存时也把引用计数减1。当引用计数变为0的时候,代表该内存不再被任何指针所引用,系统可以把它直接释放掉。 

3). 上面两点其实就是assign和retain的区别,assign就是直接赋值,从而可能引起1中的问题,当数据为int, float等原生类型时,可以使用assign。retain就如2中所述,使用了引用计数,retain引起引用计数加1, release引起引用计数减1,当引用计数为0时,dealloc函数被调用,内存被回收。 


4). copy是在你不希望a和b共享一块内存时会使用到。a和b各自有自己的内存。 


5). atomic和nonatomic用来决定编译器生成的getter和setter是否为原子操作。在多线程环境下,原子操作是必要的,否则有可能引起错误的结果。加了atomic,setter函数会变成下面这样:

 
if (property != newValue) {        
    [property release];        
    property = [newValue retain];        
}  

 

 

iOS内存管理