AutoReleasePool 和 ARC 以及Garbage Collection

AutoReleasePoolhtml

autoreleasepool並非老是被auto 建立,而後自動維護應用建立的對象。app

自動建立的狀況以下:ide

 1. 使用NSThread的detachNewThreadSelector:toTarget:withObject:方法建立新線程時,新線程自動帶有autoreleasepool。函數

 2. Main thread of Cocoa Applicationoop

 

如下狀況須要開發者建立:ui

1. 在使用Dispatch Queue時, 雖然其Pool中每一個thread都會有autoreleasepool,可是若是咱們給的task每一個都建立一些對象,並作autorelease,那若提交的task太多,好比有100000個,那在thread退出前,這些內存都沒法釋放,等於說有大量內存被佔用而釋放不了,也相似於leak了,因此這時,最好每一個提交的task都有本身的autoreleasepool,task完成了,對象也釋放了,下次再用,再分配,再釋放。this

2. 跟1相似的,若是沒有函數內部有loop,而且每一個loop都建立不少對象,若是但願這些對象早點釋放,就能夠本身建立autoreleasepoolspa

 

 

分析一下現有API的行爲。線程

NSString的方法:stringWithCString:encoding:,它建立了一個NSString對象返回了,可是它的方法名中沒有Create和Copy,意味着調用者並非這個新建對象的owner。那這個新建對象怎麼release呢?autoreleasepool必是其神祕之處,下面一點點說說它。stringWithCString:encoding:這個方法內部沒有autoreleasepool,但假設外部的某個方法是在autoreleasepool中的,這個新建對象會在外部的autoreleasepool退出時被釋放。而Foundation/Cocoa不少方法都是這樣的,就是由於它總體上依賴一個autoreleasepool的嵌套。code

#import <Foundation/Foundation.h>
#include <pthread.h>

void dosth(void *p)
{
    {
        int it = 0;
        while ( it < 10000)
        {
            [NSString stringWithCString:"ajeiauwirejafs" encoding:NSUTF8StringEncoding];
            it++;
        }
    }
}

void * dosth2(void *p)
{
    {
        int it = 0;
        while ( it < 10000)
        {
            [NSString stringWithCString:"ajeiauwirejafs" encoding:NSUTF8StringEncoding];
            it++;
        }
    }
    return NULL;
}
int main(int argc, const char * argv[])
{

    @autoreleasepool {

        for (int i = 0; i<10000; i++) {
            [NSThread detachNewThreadSelector:@selector(dosth) toTarget:NULL withObject:NULL];
            pthread_t pid;
            pthread_create(&pid, NULL, dosth2,NULL);
            sleep(10);
        }
        // insert code here...
        NSLog(@"Hello, World!");
        
    }
    
        return 0;
}

 

ARC(Automatic Reference Counting)

AutoReleasePool確實很好用,不過Apple更推薦ARC(Automatic Reference Counting)。本文的重點是能區分AutoReleasePool和ARC,並不詳盡介紹ARC。

Automatic Reference Counting (ARC) is a compiler feature that provides automatic memory management of Objective-C objects. ARC works by adding code at compile time to ensure that objects live as long as necessary, but no longer. Conceptually, it follows the same memory management conventions as manual reference counting by adding the appropriate memory management calls for you.

也就是說ARC是由編譯器在編譯後的代碼中假如retain/release的調用,編譯器可讓臨時對象的生命週期剛恰好,不會過早被release,也不會這個對象再也不須要後好久才釋放。概念上說,ARC跟手動管理同樣的,可是實際上仍是有不少差異的,好比:既然編譯器會插入Release/Retain代碼,那程序中就不容許調用retain,release, autorelease等方法了,否則就會形成內存管理的混亂,可是CFRelease,CFRetain仍是能夠用的【也就是說,ARC只管ObjectiveC那部分,而管不了C,CoreFoundation那部分】。Wiki上總結了在使用ARC時,有哪些API不能夠調用,哪些又必須用。

其中一項是:

「There is no casual casting between id and void *.

You must use special casts that tell the compiler about object lifetime. You need to do this to cast between Objective-C objects and Core Foundation types that you pass as function arguments」

也就是說在將OBJC object和CoreFoundation的對象之間Cast時,必須用特殊的cast操做符進行。

  • __bridge transfers a pointer between Objective-C and Core Foundation with no transfer of ownership.

  • __bridge_retained or CFBridgingRetain casts an Objective-C pointer to a Core Foundation pointer and also transfers ownership to you.

    You are responsible for calling CFRelease or a related function to relinquish ownership of the object.

  • __bridge_transfer or CFBridgingRelease moves a non-Objective-C pointer to Objective-C and also transfers ownership to ARC.

    ARC is responsible for relinquishing ownership of the object.

上面說ARC只管ObjC的對象,無論C/CF的對象,若是一個對象在CF中建立,要拿到ObjC中使用,若是但願ARC接管這個對象,那就使用__bridge_transfer or CFBridgingRelease,若是不但願由ARC接管,那就用__bridge。若是一個對象在ObjC中建立,要拿到CF中使用,並由CF/C釋放,那就得使用__bridge_retained or CFBridgingRetain,若是還繼續由ARC管理,就使用__bridge.

其餘的關於ARC的使用限制,就在要使用時一一查看吧,本文對ARC講到這裏,應該已經很清楚ARC跟autoreleasepool的關係了。

 

Garbage Collection

ObjC 2.0 provided an optional conservative, generational garbage collector. 若是enable了garbage collection,那麼runtime會將retain/release轉成空操做,全部的ObjC對象均可以被回收,而C的對象能夠用__strong標記符讓GC回收;A zero-ing weak subsystem was also provided such that pointers marked as "__weak" are set to zero when the object (or more simply, GC memory) is collected.可是GC在iOS上performance很差,歷來都沒有enable過,並且在OS X 10.8上也會設置爲deprecated,未來會從OSX中移除。

 

 

Reference:

ARC:https://developer.apple.com/library/mac/releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html#//apple_ref/doc/uid/TP40011226

ARC:http://clang.llvm.org/docs/AutomaticReferenceCounting.html

ARC: http://en.wikipedia.org/wiki/Automatic_Reference_Counting

相關文章
相關標籤/搜索