您的位置:首页 > 移动开发 > Objective-C

objective c 内存管理

2013-08-24 19:34 225 查看
Objective-C在管理内存时,遵循一套简单的规则。每一个对象都有一个名为"retainCount"的变量,它表示该对象有多少个引用。[java] viewplaincopyclass *obj = [class alloc];//alloc会导致retainCount为1[obj retain];//retainCount++ 通常在对象赋值之后这样做,代表它多了一个引用。[obj release];//retainCount-- 通常在使用完该对象的时候这样做。当 retainCount为0时,运行时环境会通过调用[obj dealloc]来释放对象占用的内存。下面 看一个例子:[java] viewplaincopyTest *t1 = [[Test alloc] initWithNum:12];//创建了一个对象,t1是该对象的引用,由于调用了alloc此时retainCount为1Test *t2 = t1;//此时t2也要使用该对象[t2 retain];//t2要使用对象 就必须要retain,此时retainCount为2[t1 release];//t1这时不用该对象了 就release了,也就是放弃了对象的使用权,此时retainCount为1[t2 release];//t2使用完了 就release 此时retainCount为0,立刻会调用dealloc来释放内存其实,规则很简单。谁使用谁就先retain,用完在release就可以了。这样就不会内存泄露了。oc中存在一个autorelease pool,其实它是一个NSMutableArray。把对象加入到autorelease pool:[java] viewplaincopy[obj autorelease];autorelease在释放的时候会给所有的对象发送release,如果该对象的retainCount为1,那么结果导致 retainCount为0,然后运行时就会调用对象的dealloc,以此来实现内存释放。如果你[obj retain];之后没有[obj release];在autorelease pool 释放的时候一样会内存泄露!记住autorelease pool只是给对象发送一次release而已!

【iPhone編程】alloc, retain, release 和 copy 的概念

作為一個從學習 C++,Java 開始的程式員,iPhone 編程所帶來的最大挑戰莫過於reference count 的概念。剛開始接觸 Objective C,在 XCode 裡摸來摸去,總免不了要跟這傢伙碰面:相信我,看見它多數的原因都是reference count 的概念搞不清楚所引致的。首先我們知道,要使用一個 object 的時候,我們必須要給它一個落腳的地方,且我們必須告訴系統說這一塊 memory 是我們擁有的,請不要擅自將在裡頭居住的 object 趕走。這就是我們平時寫 alloc 時所做的事情:?
分配(allocate)了一塊 memory 後,系統便會自動紀錄此 object 的 retain count 為 “1″。意即:這 object 正被一個名為 “exampleString” 的變數所擁有/聯繫著。若我們的程式某處也想擁有這個 object,我們可以:?
把這個 object 的 retain count 加一(= 2)。這樣做的話,我們就不必擔心若 exampleString有什麼三長兩短,anotherString 也受到牽連。當然,能夠擁有一個 object,自然也能放棄它。在這裡我們用 “release”。如以上例子,當我們已不再需要 exampleString,我們可以放棄 exampleString 對這個 object 的擁有權:?
這樣做便把這 object 的 retain count 減一,變為 1。意思是這 object 還有一個擁有者,那就是 anotherString 了。當我們決定了要完全釋放這個 object(deallocate)時,可以通過release anotherString,把 retain count 變0。這時,系統便會自動清除它了。當然,如果你沒有適當地 retain,又狂妄地 release object 的時候,就會遇見上面提到的那個傢伙了。會出現 bad access 錯誤的原因就是系統根本找不到你所要釋放的東西。要弄清除的概念是,retain 不代表分配了一個新的 memory筆者便曾經搞錯了這個概念。如果你想要複製一個object,你所需要的指令是 “copy”。?
以上兩行指令已經分配了兩塊 memory。對其中一個 object 所做的改變,不會影響到另外一個,且他們各自的 retain count 為1。應該說明的是,由於 object 的性質各有不同,如果有需要用到copy指令,你應該為你的object class 加入 -(id)copyWithZone:(NSZone*)zone 函數。有興趣知道更多的話,可以到這裡參考。。通常在method中把参数赋给成员变量时需要retain。是为了防止 参数的计数器为0 被销毁了 但是成员变量还在使用这个参数 这样就会出错一个一直困惑的问题:
-(void) setFirst : (NSString *) f
{
[f retain];
[first release];
first = f;
}
对于first来说,先release后赋值,是因为如果先赋值,first就指向了f,导致first先前指向的内存无法被访问到,无法释放,造成内存泄露。
先retain再release是为了防止f和first本身指向的是同一个地址,如果直接release,再retain的话会导致该地址引用计数器为0,内存被释放,f和first均成为野指针
如果不要前两行,直接赋值的话,f可能会被调用这个函数的调用者给释放掉,就导致了first无法在该类实例中继续被使用了,因此赋值的时候要把它的引用计数增加1
其实,下面这种说法更好理解一些:
首先形参f的作用域为setFirst函数内,所以当setFirst函数结束时,f会被释放,而first是在setFirst运行完后用到的(NSString *first =[[NSString alloc] initWithCString: "Tom"];
),所以此处 retain; 当first已经存在时,就需要先把它释放,再赋值,如果没有释放,会使得原来的数据再也无法访问到,造成内存泄露。有可能f和first指向同一个地址,直接赋值的话,f可能会被调用这个函数的调用者给释放掉。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: