內(nèi)存管理
內(nèi)存管理原則
自己生成的對(duì)象自己持有
alloc产阱、new、copy捞奕、mutable以及符合以這些關(guān)鍵字為前綴并且符合駝峰拼寫(xiě)法命名的都是自己生成并持有的非自己生成的對(duì)象自己也能持有
除alloc、new、copy雏胃、mutableCopy等去得的對(duì)象都為非自己生成但自己持有,我們也有義務(wù)對(duì)其進(jìn)行釋放如果在MRC中不再需要自己持有的對(duì)象時(shí)釋放
自己持有的對(duì)象需要釋放志鞍,但如果僅僅是對(duì)象存在但不持有瞭亮,則不需要自己釋放對(duì)象,例如取得注冊(cè)到Autorelease表中的對(duì)象則不需要我們釋放非自己持有的對(duì)象無(wú)法釋放
如果過(guò)度釋放會(huì)因?yàn)獒尫帕朔亲约撼钟械膶?duì)象而引起崩潰固棚,如果釋放取得的對(duì)象存在但自己不持有统翩,也會(huì)崩潰仙蚜。
內(nèi)存管理實(shí)現(xiàn)
alloc\retain\release\delloc
猜測(cè)蘋(píng)果的引用計(jì)數(shù)是通過(guò)散列表來(lái)管理引用計(jì)數(shù)的,主要通過(guò)CFDoExternRefOperation來(lái)進(jìn)行分發(fā)操作的厂汗,大概步驟是先通過(guò)函數(shù)找到散列表Table委粉,然后根據(jù)retainCount/retain/release等進(jìn)行分發(fā)操作來(lái)記錄引用計(jì)數(shù)autorelease
其實(shí)跟C語(yǔ)言中得局部變量類似,超出作用域則自動(dòng)廢棄娶桦。其生命周期可以看做:生成并持有NSAutoreleasePool對(duì)象-調(diào)用已分配對(duì)象的autorelease方法-廢棄NSautoreleasePool(這里被分配的對(duì)象也會(huì)自動(dòng)調(diào)用release進(jìn)行釋放)贾节,NSRunLoop每次循環(huán)時(shí)都會(huì)將廢棄的NSAutoreleasePool進(jìn)行處理,大量讀取圖像并進(jìn)行操作的時(shí)候最好每個(gè)都放在AutoreleasePool中進(jìn)行不然會(huì)產(chǎn)生大量autorelease衷畦,造成內(nèi)存不足栗涂。其實(shí)現(xiàn)可看做 :push到Pool中--autorelease 將對(duì)象加到autoreleasepool池中--pop 相對(duì)于廢棄NSAutoreleasePool對(duì)象
ARC規(guī)則
所有權(quán)修飾符
strong 修飾符
oc中的對(duì)象默認(rèn)修飾符都是strong類型,通過(guò)strong修飾無(wú)需再retain或者releaseweak修飾符
weak的出現(xiàn)是為了解決循環(huán)引用而引起的內(nèi)存泄露祈争,他是弱引用不持有對(duì)象斤程,而且他會(huì)自動(dòng)置為nil,unsafe_unretained修飾符
是不安全的修飾符菩混,他不屬于編譯器的內(nèi)存管理對(duì)象忿墅,因此使用它得非常小心,容易造成垂懸指針墨吓,所以使用它時(shí)一定要保證他的對(duì)象存在autorelease修飾符
被autorelease修飾的對(duì)象會(huì)被注冊(cè)到autoreasePool池中球匕,保證其對(duì)象存在 但不被持有,一般除了alloc/new/copy/mutableCopy以及符合駝峰命名法生成的對(duì)象都是注冊(cè)到autorelease中帖烘,而且weak修飾的對(duì)象也會(huì)被注冊(cè)到autorelease中亮曹,而且id的指針都是默認(rèn)被autorelease修飾,
規(guī)則
- 不能使用retain/release/autorealse/dealloc/retainCount/autorelease
- 不能使用NSAllocateObject和NSDeallocateObject
- 須遵循內(nèi)存管理的命名法則
- 使用@autorelease{}代替NSAutoreleasePool
- 不能使用區(qū)域NSZone
- 對(duì)象變量不能作為C語(yǔ)言的結(jié)構(gòu)體的的成員 需加unsafe_unretained修飾符
- 顯示轉(zhuǎn)換”id“ 和”void *“ 通過(guò)bridge(bridge_retained和bridge_transfer) 可以進(jìn)行互換
ARC實(shí)現(xiàn)
- strong修飾符
在運(yùn)行時(shí)自動(dòng)給我上了release
NSObject *obj = [[NSObject alloc] init];
id obj = objc_msgSend(NSObject,@selector(alloc));
objc_msgSend(obj,@selector(init));
objc_release(obj);
NSAarray *arr = [NSArray array];
+(id)array{
return [[NSArray alloc] init];
}
id obj = objc_msgSend(NSArray,@selector(init));
objc_retainAutoreleaseReturnValue(obj);
objc_release(obj);
id obj = objc_msgSend(NSArray,@selector(alloc));
objc_msgSend(obj,@selector(init));
return objc_autoreleaseReturnValue(obj);
objc_autoreleaseReturnValue 和 objc_retainautoreleasedReturnValue成對(duì)出現(xiàn),不需要注冊(cè)到autoreleasepool中秘症,而直接進(jìn)行傳遞保證對(duì)象的存在照卦,這一過(guò)程達(dá)到了最優(yōu)化
- weak修飾符
{
id obj1 = obj;
}
id obj1;
objc_initWeak(&obj1,obj);
objc_destoryWeak(&obj1,0);
通過(guò)objc_initWeak函數(shù)初始化weak 修飾的變量,在變量作用域結(jié)束時(shí)調(diào)用objc_destoryWeak函數(shù)釋放該變量乡摹。其中objc_storeWeak(&obj1,obj)處理役耕,如果obj超出了作用域objc_storeWeak(&obj1,0),然后把變量的地址從weak表中移除聪廉,NSMachPort不支持weak
- autorelease修飾符
id pool = objc_autoreleasePoolPush();
id obj = objc_msgSend(NSObject,@selector(alloc));
objc_msdSend(obj,@selector(init));
objc_autorelease(obj);
objc_autoreleasePoolPop(pool);