AutoReleasePool 和 ARC 以及Garbage Collection


AutoReleasePool

autoreleasepool並不是總是被auto 創建,然后自動維護應用創建的對象。

自動創建的情況如下:

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

 2. Main thread of Cocoa Application

 

以下情況需要開發者創建:

1. 在使用Dispatch Queue時, 雖然其Pool中每個thread都會有autoreleasepool,但是如果我們給的task每個都創建一些對象,並做autorelease,那若提交的task太多,比如有100000個,那在thread退出前,這些內存都無法釋放,等於說有大量內存被占用而釋放不了,也類似於leak了,所以這時,最好每個提交的task都有自己的autoreleasepool,task完成了,對象也釋放了,下次再用,再分配,再釋放。

2. 跟1類似的,如果沒有函數內部有loop,並且每個loop都創建很多對象,如果希望這些對象早點釋放,就可以自己創建autoreleasepool

 

 

分析一下現有API的行為。

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

#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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM