NSAutoreleasePool ऑटोरेलिज पूल कैसे काम करता है?


95

जैसा कि मैं इसे समझता हूं, एक आबंटित , नई या प्रतिलिपि के साथ बनाई गई कुछ भी मैन्युअल रूप से जारी करने की आवश्यकता है। उदाहरण के लिए:

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

मेरा सवाल है, हालांकि, यह सिर्फ मान्य नहीं होगा ?:

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

जवाबों:


68

हां, आपका दूसरा कोड स्निपिट पूरी तरह से मान्य है।

हर बार -ऑटोरेलेज़ को किसी ऑब्जेक्ट में भेजा जाता है, इसे आंतरिक-सबसे ऑटोरेलिज़ पूल में जोड़ा जाता है। जब पूल को सूखा जाता है, तो यह पूल में सभी ऑब्जेक्ट्स को -release भेजता है।

ऑटोरेलिस पूल बस एक सुविधा है जो आपको "बाद में" तक भेजने के लिए अनुमति देने से रोकती है। यह "बाद में" कई स्थानों पर हो सकता है, लेकिन कोको GUI ऐप्स में सबसे आम वर्तमान रन लूप चक्र के अंत में है।


5
यदि मेरे पास एक लूप नहीं है, तो वर्तमान रन लूप चक्र का अंत कहां है?
धन्यवाद

24
"इनर-मोस्ट" "इनर-मोस्ट" नहीं होना चाहिए?
माइक वेलर

an objectहोना चाहिए an object that is a subclass of NSObject or NSProxy and doesn't override -autorelease

1
संपादित करें: बाहरी-सबसे भीतरी-सबसे बदल गया।
5

1
महत्वपूर्ण: यदि आप स्वचालित संदर्भ गणना (ARC) का उपयोग करते हैं, तो आप सीधे ऑटोरेलिज़ पूल का उपयोग नहीं कर सकते। इसके बजाय, आप @autoreleasepool ब्लॉक का उपयोग करते हैं। डेवलपर
.apple.com/library/mac/#documentation/Cocoa/Reference/…

37

NSAutoreleasePool: नाली बनाम रिलीज़

के कार्य के बाद से drainऔर releaseभ्रम पैदा हो रहा है, यह यहाँ स्पष्ट करने लायक हो सकता है (हालांकि यह प्रलेखन में शामिल है ...)।

कड़ाई से बोलना, बड़े चित्र के दृष्टिकोण drainसे समतुल्य नहीं है release:

एक संदर्भ-गणना वाले वातावरण में, drainसमान संचालन करता है release, इसलिए दोनों समान अर्थ में हैं। जोर देने के लिए, इसका मतलब है कि आप पूल का रिसाव नहीं करते हैं यदि आप drainइसके बजाय उपयोग करते हैं release

कचरा एकत्र करने वाले वातावरण में, releaseएक नो-ऑप है। इस प्रकार इसका कोई प्रभाव नहीं है। drainदूसरी ओर, कलेक्टर को एक संकेत मिलता है कि इसे "यदि आवश्यक हो तो इकट्ठा करना चाहिए"। इस प्रकार एक कचरा-एकत्र किए गए वातावरण में, drainसिस्टम संतुलन संग्रह झाडू का उपयोग करने में मदद करता है।


4
यह मौलिक रूप से असंभव है 'लीक' ए NSAutoreleasePool। ऐसा इसलिए है क्योंकि पूल स्टैक की तरह काम करते हैं। एक पूल को इंस्टेंट करना उस पूल को उस थ्रेड्स ऑटोरेलिज पूल स्टैक के शीर्ष पर धकेलता है। -releaseस्टैक से पॉप करने के लिए उस पूल का कारण बनता है और इसके ऊपर धकेल दिए गए किसी भी पूल, लेकिन जो भी कारण के लिए पॉप नहीं किया गया था।
जौने

7
किस तरह से यह प्रासंगिक है जो मैंने लिखा था?
mmalc

2
मुझे पसंद है कि कैसे वह बोल्ड और करने के लिए समय ले लिया। भगवान!
बिली ग्रे

17

जैसा कि पहले ही बताया गया है, आपका दूसरा कोड स्निपेट सही है।

मैं ऑटोरेलेज पूल का उपयोग करने का एक और अधिक उपयुक्त तरीका सुझाना चाहूंगा जो सभी वातावरणों पर काम करता है (रेफ गिनती, जीसी, एआरसी) और नाली / रिलीज भ्रम से भी बचता है:

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

ऊपर दिए गए उदाहरण में कृपया @autoreleasepool ब्लॉक को नोट करें । यह यहाँ प्रलेखित है


2
कृपया ध्यान दें, कि एआरसी के साथ ऑटोरिलिज़ की अनुमति नहीं है।
dmirkitanov

1
स्पष्ट करने के लिए, @autoreleasepoolएआरसी के साथ ब्लॉक का उपयोग करना होगा ।
साइमन

7

नहीं तुम गलत हो। दस्तावेज़ में स्पष्ट रूप से कहा गया है कि गैर-जीसी के तहत -drain -release के बराबर है, जिसका अर्थ है कि NSAutoreleasePool लीक नहीं किया जाएगा।


मैं सोचता था कि अगर मामला होता तो Xcode कोड कैसे उत्पन्न करता। मैंने -drain का उपयोग किया क्योंकि मुझे लगा कि यह Xcode द्वारा उत्पन्न कोड के आधार पर -release के बराबर था।
जेम्स समर्स

1
डेवलपर को 'लीक' करना मौलिक रूप से असंभव है NSAutoreleasePool: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…
johne

0

मैं Apple से क्या पढ़ता हूं: "ऑटोरेलिज पूल ब्लॉक के अंत में, ब्लॉक के भीतर एक ऑटोरेलिज संदेश प्राप्त करने वाली वस्तुओं को एक रिलीज संदेश भेजा जाता है - प्रत्येक वस्तु को ब्लॉक के भीतर एक ऑटोरिएल संदेश भेजे जाने पर हर बार रिलीज संदेश प्राप्त होता है। "

https://developer.apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html


0

किसी वस्तु को जारी करने के बजाय ऑटोरेलिज भेजना उस वस्तु के जीवनकाल को कम से कम तब तक बढ़ाता है जब तक कि पूल को सूखा न जाए (यह तब हो सकता है जब वस्तु को बाद में बरकरार रखा जाए)। एक वस्तु को कई बार उसी पूल में डाला जा सकता है, जिस स्थिति में उसे हर बार पूल में डालने के लिए एक रिलीज संदेश प्राप्त होता है।


-2

हां और ना। यदि आप NSAutoreleasePool ऑब्जेक्ट को मेमोरी में "लीक" करते हैं, तो रिलीज के बजाय नाली का उपयोग करके मेमोरी में डाल देंगे यदि आप इसे एकत्र किए गए कचरे (मेमोरी प्रबंधित नहीं) पर्यावरण के तहत चलाते हैं। यह "रिसाव" बस NSAutoreleasePool का उदाहरण देता है "पहुंच योग्य" जीसी के तहत कोई मजबूत पॉइंटर्स के साथ किसी भी अन्य ऑब्जेक्ट की तरह, और अगली बार GC रन होने पर ऑब्जेक्ट को साफ किया जाएगा, जो कॉल के बाद बहुत अच्छी तरह से हो सकता है -drain:

नाली

कचरा एकत्र किए गए वातावरण में, कचरा संग्रहण को ट्रिगर करता है यदि पिछले संग्रह के बाद से आवंटित मेमोरी वर्तमान सीमा से अधिक है; अन्यथा रिहाई के रूप में व्यवहार करता है। ... कचरा-एकत्र किए गए वातावरण में, यह विधि अंततः कॉल करती है objc_collect_if_needed

अन्यथा, यह -releaseगैर-जीसी के तहत व्यवहार करने के समान है , हां। जैसा कि अन्य ने कहा है, -releaseजीसी के तहत एक नो-ऑप है, इसलिए यह सुनिश्चित करने का एकमात्र तरीका है कि जीसी के तहत पूल फ़ंक्शन ठीक से हो -drain, और -drainगैर-जीसी के -releaseतहत बिल्कुल गैर-जीसी के तहत काम करता है , और यकीनन इसकी कार्यक्षमता को अधिक स्पष्ट रूप से बताता है। कुंआ।

मुझे यह बताना चाहिए कि आपके कथन "नए, आवंटित या init के साथ कुछ भी कहा जाता है" में "init" शामिल नहीं होना चाहिए (लेकिन "प्रतिलिपि" शामिल होना चाहिए), क्योंकि "init" स्मृति आवंटित नहीं करता है, यह केवल ऑब्जेक्ट (निर्माता) सेट करता है फैशन)। यदि आपको एक आबंटित वस्तु प्राप्त होती है और आपका कार्य केवल init कहलाता है, तो आप इसे जारी नहीं करेंगे:

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

यह आपके द्वारा पहले से शुरू की गई तुलना में किसी भी अधिक मेमोरी का उपभोग नहीं करता है (यह मानते हुए init ऑब्जेक्ट्स को तुरंत नहीं करता है, लेकिन आप वैसे भी उन लोगों के लिए जिम्मेदार नहीं हैं)।


मैं इस उत्तर को छोड़ने में सहज महसूस नहीं करता हूं क्योंकि जब नाली के बारे में आपकी जानकारी सही नहीं होती है डेवलपर देखें ।apple.com/documentation/Cocoa/Reference/Foundation/… अपडेट करें और मैं फिर से स्वीकार करूंगा।
जेम्स सुमेर

उत्तर के बारे में क्या गलत है? कचरा एकत्र किए गए वातावरण में (जैसा कि कहा गया है), ड्रेन ऑटोरेलिजपूल को नष्ट नहीं करता है, इसलिए आप मेमोरी को लीक कर देंगे जब तक आप रिलीज का उपयोग नहीं करते। मेरे द्वारा सूचीबद्ध उद्धरण घोड़े के मुंह से सीधे था, नाली पर डॉक्स।
लोरेन सहगल

1
लॉरेन: GC के तहत, - [NSAutoreleasePool drain] एक संग्रह को ट्रिगर करेगा। -टेक्ट, -रेलिज, और -ऑटोर्लीज को कलेक्टर द्वारा अनदेखा किया जाता है; यही कारण है कि -drain का उपयोग GC के तहत ऑटोरेलिज पूल पर किया जाता है।
क्रिस हैनसन

'ड्रेन' के लिए दस्तावेज़ीकरण में: एक प्रबंधित मेमोरी वातावरण में, यह कॉलिंग रिलीज़ के समान व्यवहार करता है। यदि आप रिलीज के बजाय 'ड्रेन' का उपयोग करते हैं तो इस प्रकार आप मेमोरी को लीक नहीं करेंगे ।
mmalc

-[NSAutoreleasePool release]एक कूड़े-एकत्र वातावरण में एक नो-ऑप है। -[NSAutoreleasePool drain]संदर्भ-गणना और कचरा-एकत्रित वातावरण दोनों में काम करता है।
जोनाथन स्टर्लिंग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.