2014-07-25 26 views
7

Sanırım kendi iş parçacığı herhangi autoreleasepool yaratmadı buşimdi NSThread otomatik olarak otomatik oluşturucu oluşturmuyor mu?

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil]; 
    [thread start]; 
} 

-(void)test 
{ 
    MyClass *my = [[[MyClass alloc] init] autorelease]; 
    NSLog(@"%@",[my description]); 
} 

gibi test kodu var ama ne zaman iplik çıkış, nesne "benim" sadece dealloc.why?

Ben kendi autoreleasepool oluşturmak

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(test) object:nil]; 
    [thread start]; 
} 

-(void)test 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    MyClass *my = [[[MyClass alloc] init] autorelease]; 
    NSLog(@"%@",[my description]); 
} 

aşağıdaki gibi benim test kodunu değiştirmek ama ne zaman iplik çıkış boşaltıp değil olsa bile. nesne "benim" yine de hala dealloc olabilir. niye ya?

Ben ARC

+0

Nesnemin nasıl serbest bırakıldığını söylüyorsun? –

+0

Gerekli bilgileri alabilir misin? –

+0

Çünkü "benim" in dealloc yönteminde bir kesme noktası var – eliudnis

cevap

1

Apple documentation says (4 inci paragraf) kullanmayan Xcode5 ve kullanımı:

Her zamanki alloc ve init mesajları ile bir NSAutoreleasePool nesnesi oluşturmak ve (kanallı şekilde imha veya serbest bırakın - arasındaki farkı anlamak için, Çöp Toplama bölümüne bakın). Bir autorelease havuzunu tutamayacağınız için (ya da bunu otomatik olarak kaldırmaya bakın - saklayın ve otomatik olarak devam ettirin), bir havuzu boşaltan sonuçta onu serbest bırakma etkisine sahiptir. , her zaman (bir yöntemin veya işlevin veya bir döngünün gövdesinin) aynı bağlamda bir otomatikleştirme havuzu oluşturmalıdır. Bu, olarak oluşturulmuştur. Daha fazla bilgi için Autorelease Havuz Bloklarını Kullanma konusuna bakın.

16

Bu belgelenmiş değil, ama cevap OS X 10.9+ ve iOS 7+ üzerine, Evet olarak görünmektedir.

Objective-C çalışma zamanı open-source olup, neler olduğunu görmek için kaynağı okuyabilirsiniz. Geçerli iş parçacığı üzerinde bir havuz olmadan bir autorelease gerçekleştirirseniz, çalışma zamanının en son sürümü (OS X 10.10 ve iOS 8 ile birlikte gelen 646) gerçekten bir havuz ekler. NSObject.mm yılında: İlk havuzu iterken

static __attribute__((noinline)) 
id *autoreleaseNoPage(id obj) 
{ 
    // No pool in place. 
    assert(!hotPage()); 

    if (obj != POOL_SENTINEL && DebugMissingPools) { 
     // We are pushing an object with no pool in place, 
     // and no-pool debugging was requested by environment. 
     _objc_inform("MISSING POOLS: Object %p of class %s " 
        "autoreleased with no pool in place - " 
        "just leaking - break on " 
        "objc_autoreleaseNoPool() to debug", 
        (void*)obj, object_getClassName(obj)); 
     objc_autoreleaseNoPool(obj); 
     return nil; 
    } 

    // Install the first page. 
    AutoreleasePoolPage *page = new AutoreleasePoolPage(nil); 
    setHotPage(page); 

    // Push an autorelease pool boundary if it wasn't already requested. 
    if (obj != POOL_SENTINEL) { 
     page->add(POOL_SENTINEL); 
    } 

    // Push the requested object. 
    return page->add(obj); 
} 

Bu işlev denir (bu durumda bir şey POOL_SENTINEL olduğu itilmiş) veya hiçbir havuzlu sallanmasını. İlk havuz itildiğinde, otorite yığınını ayarlar. Ancak, koddan gördüğünüz gibi, DebugMissingPools çevre değişkeni ayarlanmadığı sürece (varsayılan olarak ayarlanmamıştır), otomatikleştirme havuzsuz olarak yapıldığında, otorite yığınını da ayarlar ve ardından bir havuzu iter (POOL_SENTINEL).

Benzer şekilde, (diğer koda bakmadan izlenmesi biraz zor, ancak bu konu ilgili bölümdür) iş parçacığı imha edildiğinde (ve İş Parçacığı Depolaması yok edilir), otorite yığınındaki her şeyi serbest bırakır. (yani pop(0); yaptığı da budur) bu yüzden son havuz pop kullanıcıya dayanmaz: Ayrıca

static void tls_dealloc(void *p) 
{ 
    // reinstate TLS value while we work 
    setHotPage((AutoreleasePoolPage *)p); 
    pop(0); 
    setHotPage(nil); 
} 

(X 10.9 ve iOS 7 işletim sistemi ile birlikte gelen 551.1, çalışma zamanında) önceki sürümü, Bunu, NSObject.mm:

'dan görebileceğiniz gibi yaptınız

Ancak bundan önceki sürüm (532.2, OS X 10 ile birlikte geldi.8 ve iOS 6), does not:

static __attribute__((noinline)) 
id *autoreleaseSlow(id obj) 
{ 
    AutoreleasePoolPage *page; 
    page = hotPage(); 

    // The code below assumes some cases are handled by autoreleaseFast() 
    assert(!page || page->full()); 

    if (!page) { 
     assert(obj != POOL_SENTINEL); 
     _objc_inform("Object %p of class %s autoreleased " 
        "with no pool in place - just leaking - " 
        "break on objc_autoreleaseNoPool() to debug", 
        obj, object_getClassName(obj)); 
     objc_autoreleaseNoPool(obj); 
     return NULL; 
    } 

    do { 
     if (page->child) page = page->child; 
     else page = new AutoreleasePoolPage(page); 
    } while (page->full()); 

    setHotPage(page); 
    return page->add(obj); 
} 

Not herhangi pthread s için yukarıdaki çalışmalar, sadece NSThread s.

Temel olarak, OS X 10.9+ veya iOS 7+ işletim sistemlerinde çalışıyorsanız, havuz bulunmayan bir iş parçacığındaki otomatik arama, bir sızıntıya neden olmamalıdır. Bu belgelenmemiş ve bir iç uygulama detayıdır, bu yüzden Apple'ın gelecekteki bir işletim sisteminde değiştirebileceğinden emin olun. Bununla birlikte, bu özelliği kaldırmanın neden bir neden görmediğini görüyorum, çünkü basittir ve otorite havuzlarının işleyiş şeklini tamamen yeniden yazmazlarsa, yalnızca faydaları ve dezavantajları vardır.

+0

Üstün yanıt. Büyük dedektif çalışması. Mesaj için teşekkürler. (Oy verildi) –

+1

Otomatik temizleme işleminin ana iş parçacığı için * yapılmadığını unutmayın. Temizleme işlevi 'tls_dealloc',' pthread_key_init_np' için bir çağrıyla eklenen bir iş parçacığı yerel depolama (TLS) yıkıcısıdır. Bu yıkıcılar, bir iş parçacığı başlangıç ​​rutinden döndüğünde örtülü olarak çağrılan pthread_exit'ten çağrılır, ancak ana iş parçacığı için geçerli değildir. Yani 'autoreleaseNoPage' tarafından eklenen kapalı havuz boşaltılmayacaktır. Http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_exit.html sayfasına bakın. –

İlgili konular