objective-c对内存管理的疑问


我是从xcode 4才开始认真学习ios开发,但是由于它用的是LLVM 3,所以导致我在看很多文档时会发现很多令人疑惑的地方。

例如在以前的很多代码中,一个对象被 alloc 然后被使用完后,会立即调用一个 release 方法。比如类似下面的代码

ClassA *a = [[ClassA alloc] init];
ClassB *b = [[ClassB alloc] init];

[b setProperty:a];
[a release];

这种类似的代码很让人费解,我的猜测,如果这个代码可以正常运行的话,那么 release 方法实际并不是一个实际释放的方法,它只会做一个类似标记的玩意,在生命周期结束后再自己释放。

我依稀记得objective-c中有一个 retain 的机制,那么是否在这里的 release 只是把 retain 的计数减一了呢?那么什么样的行为会导致 retain 计数加一呢?llvm 3里面为啥可以抛弃这种方法呢?

ios objective-c llvm

天真真是无邪 10 years, 5 months ago

先说release,不是直接释放内存,是引用计数-1,而当引用计数0的时候,sdk会gc掉这段内存。应用的main函数里可以看到,有初始化一个AutoRealesePool,就是干这个。
另外,每个对象都有autorelease方法,对他调用一把autorelease后,就不用手动release了。
再看示例代码,这个要看你 ClassB 里 property 的定义:
如果是@property (copy) ClassB * b,那么setProperty的时候内存里会复制一个a,付给b。则(a-> mema[rc=1], b->memb[rc=1])
如果是@property (retain) ClassB * b,就给a的引用计数+1,b还是指向这段内存。则(a-> mema[rc=2] <-b)
所以,setProperty以后,对a调用release的时候,就是把a指向的内存段的rc-1。copy的情况下,a已经不可以调用了,掉了就会BAD_ACCESS,retain的情况下,a还可以调用,因为他的rc=2-1=1。
再说llvm3里抛弃这个的问题,llvm3有个特性,叫ARC,就是AutoReferenceCount,rc被自动管理了。在ARC打开的文件中,release autorelease retain 都是不允许使用的。在XCode的编译规则中可以加参数选择是否使用ARC编译某个文件。
后ARC时代,要注意属性是函数局部的,还是类全局的这些,因为,开发者已经不需要手动回收内存,ARC会依据他的可见性,或者是生命周期去处理。在使用完某个对象后,要 =nil一下,ARC会马上干掉他。
最后,在前ARC时代几个简单的规则:
使用alloc创建的实例引用计 rc=1
作为addObject:等方法的参数 rc+=1
作为removeObject:等方法的参数 rc-=1
调用removeFromeOOXX方法 rc-=1
调用 retain rc+=1
调用 copy 复制一份 rc不变
调用 release rc-=1
---- 使用建议 ----
使用alloc创建后,一定要使用release释放,或调用autorelease交给系统管理
add以后,一定记得remove

angel-葬 answered 10 years, 5 months ago

Your Answer