NSAutoreleasePool otomatik yayın havuzu nasıl çalışır?


95

Anladığım kadarıyla, bir tahsis , yeni veya kopya ile oluşturulan her şeyin manuel olarak serbest bırakılması gerekiyor. Örneğin:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

Yine de sorum bu kadar geçerli olmaz mıydı ?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}

Yanıtlar:


68

Evet, ikinci kod parçacığınız tamamen geçerli.

-Autorelease bir nesneye her gönderildiğinde, en içteki otomatik serbest bırakma havuzuna eklenir. Havuz boşaltıldığında, havuzdaki tüm nesnelere -release gönderir.

Otomatik serbest bırakma havuzları basitçe -release gönderimini "daha sonraya" ertelemenizi sağlayan bir rahatlıktır. Bu "daha sonra" birkaç yerde olabilir, ancak Cocoa GUI uygulamalarında en yaygın olanı mevcut çalışma döngüsü döngüsünün sonundadır.


5
Döngüm yoksa, mevcut çalışma döngüsü döngüsünün sonu nerede?
teşekkürler

24
"En dıştaki" "en içteki" olmamalı mı?
Mike Weller

an objectolmalıdır an object that is a subclass of NSObject or NSProxy and doesn't override -autorelease.

1
DÜZENLEME: En dıştan en içe değiştirildi.
chakrit

1
Önemli: Otomatik Referans Sayımı (ARC) kullanıyorsanız, otomatik yayın havuzlarını doğrudan kullanamazsınız. Bunun yerine, @autoreleasepool bloklarını kullanırsınız. Gönderen developer.apple.com/library/mac/#documentation/Cocoa/Reference/...
Md Mahbubur Rahman

37

NSAutoreleasePool: boşaltma ve serbest bırakma

İşlevi drainve releasekarışıklığa neden olduğu görüldüğünden, burada açıklığa kavuşturmaya değer olabilir (her ne kadar bu belgelerde ele alınsa da ...).

Kesinlikle büyük resmi perspektiften, konuşma drainolduğunu değil eşdeğerdir release:

Referans sayılan bir ortamda, drainaynı işlemleri gerçekleştirir release, bu nedenle ikisi bu anlamda eşdeğerdir. Vurgulamak için bu araçlar size do not kullandığınız takdirde bir havuz sızıntısı drainziyade release.

Çöp toplanan bir ortamda, releaseişlem yok. Bu nedenle hiçbir etkisi yoktur. draindiğer yandan, toplayıcıya "gerekirse toplaması" gerektiğine dair bir ipucu içerir. Böylelikle çöp toplama ortamında kullanmak drain, sistemin toplama taramalarını dengelemesine yardımcı olur.


4
A 'sızdırmak' temelde imkansızdır NSAutoreleasePool. Bunun nedeni, havuzların bir yığın gibi çalışmasıdır. Bir havuzun örneklenmesi, bu havuzu bu iş parçacığı otomatik yayın havuz yığınının üstüne iter. -releasebu havuzun yığından fırlamasına VE üstüne itilen havuzların, ancak herhangi bir nedenle patlamamasına neden olur.
johne

7
Bu, yazdıklarımla ne şekilde alakalı?
mmalc

2
Cesur AND olmaya zaman ayırmasını seviyorum. SNAP!
Billy Gray

17

Daha önce belirtildiği gibi, ikinci kod pasajınız doğrudur.

Tüm ortamlarda çalışan (ref sayma, GC, ARC) ve ayrıca boşaltma / bırakma karışıklığını önleyen otomatik yayın havuzunu kullanmanın daha kısa ve öz bir yolunu önermek isterim:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

Yukarıdaki örnekte lütfen @autoreleasepool bloğuna dikkat edin . Bu burada belgelenmiştir .


2
ARC ile otomatik yayına izin verilmediğini lütfen unutmayın.
dmirkitanov

1
Açıklığa kavuşturmak için, @autoreleasepoolARC ile bloğu kullanmak gerekir .
Simon

7

Hayır, sen hatalısın. Dokümantasyon olmayan GC altında, NSAutoreleasePool olacak anlamına -Yayın eşdeğer -DRAIN olduğunu açıkça belirtmektedir değil sızdırılmış olması.


Böyle bir durumda Xcode'un neden -drain ile kod üreteceğini merak ettim. -Drain kullandım çünkü Xcode tarafından üretilen koda göre -release'e eşdeğer olduğunu düşündüm.
James Sumners



0

Bir nesneye serbest bırakma yerine otomatik bırakma göndermek, o nesnenin ömrünü en azından havuzun kendisi boşaltılıncaya kadar uzatır (nesne daha sonra tutulursa daha uzun olabilir). Bir nesne aynı havuza birkaç kez konulabilir, bu durumda havuza her konulduğunda bir yayınlama mesajı alır.


-2

Evet ve hayır. Sonunda dize belleğini serbest bırakıp NSAutoreleasePool nesnesini, bunu çöp toplama (bellek tarafından yönetilmeyen) bir ortamda çalıştırırsanız, serbest bırakma yerine boşaltma kullanarak belleğe "sızdırırsınız". Bu "sızıntı", NSAutoreleasePool örneğini, GC altındaki güçlü işaretçileri olmayan diğer nesneler gibi "erişilemez" hale getirir ve nesne, GC'nin bir sonraki çalışmasında temizlenir, bu da aşağıdakilere yapılan çağrıdan hemen sonra olabilir -drain:

boşaltmak

Çöp toplama ortamında, son toplamadan bu yana ayrılan bellek geçerli eşikten büyükse çöp toplamayı tetikler; aksi takdirde serbest bırakma olarak davranır. ... Çöp toplanan bir ortamda, bu yöntem sonuçta çağırır objc_collect_if_needed.

Aksi takdirde, -releaseGC olmayanlarda nasıl davrandığına benzer , evet. Başkalarının da belirttiği gibi, -releaseGC altında işlemsizdir, bu nedenle havuzun GC altında düzgün çalıştığından emin olmanın tek yolu geçmektir -drainve -drainGC -releaseolmayanlar altında tam olarak GC olmayanlar gibi çalışır ve tartışmalı olarak işlevselliğini daha açık bir şekilde iletir iyi.

"Yeni, tahsis veya init ile çağrılan herhangi bir şey" ifadenizin "init" içermemesi gerektiğini (ancak "kopya" içermesi gerektiğini) belirtmeliyim, çünkü "init" bellek ayırmaz, sadece nesneyi (yapıcı moda). Tahsis edilmiş bir nesne aldıysanız ve işleviniz yalnızca init'i çağırdıysa, onu serbest bırakmazsınız:

- (void)func:(NSObject*)allocd_but_not_init
{
    [allocd_but_not_init init];
}

Bu zaten başladığınızdan daha fazla bellek tüketmez (init'in nesneleri somutlaştırmadığını varsayarsak, ancak bunlardan zaten sorumlu değilsiniz).


Tahliye hakkındaki bilgileriniz pek doğru olmadığında bu cevabı kabul edilmiş olarak bırakmaktan kendimi rahat hissetmiyorum. Developer.apple.com/documentation/Cocoa/Reference/Foundation/… Güncellemeye bakın ve yeniden kabul edeceğim.
James Sumners

Yanıtla ilgili yanlış olan nedir? Bunu (belirtildiği gibi) bir çöp toplanan ortamında, drenaj, AutoReleasePool silmez olacak sen salınımını kullanılan sürece bellek sızdırıyor. Listelediğim alıntı, doğrudan atın ağzından, dökülen dokümanlardı.
Loren Segal

1
Loren: GC altında, - [NSAutoreleasePool drenaj] bir toplama işlemini tetikleyecektir. -retain, -release ve -autorelease, toplayıcı tarafından yok sayılır; bu nedenle GC altındaki otomatik yayın havuzlarında -drain kullanılır.
Chris Hanson

'Drenaj' belgelerinde: Yönetilen bir bellek ortamında, bu, yayın çağırma ile aynı şekilde davranır. Böylece, olur değil bunun yerine salımının 'göçünü kullanırsanız bellek sızdırıyor.
mmalc

-[NSAutoreleasePool release]Çöp toplanan bir ortamda işlem yapılmaz. -[NSAutoreleasePool drain]hem referans sayılan hem de çöp toplama ortamlarında çalışır.
Jonathan Sterling
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.