2009-07-18 6 views
5

मैं स्टैक ओवरफ्लो पर पूछे गए प्रश्नों को देख रहा हूं, लेकिन ऑब्जेक्टिव-सी में मेमोरी मैनेजमेंट के बारे में बहुत कुछ है कि मुझे वह जवाब नहीं मिला जो मैं ढूंढ रहा था।संग्रह में वस्तुओं को जोड़ने से पहले autorelease का उपयोग करें?

प्रश्न यह है कि यदि संग्रह में एक नव निर्मित ऑब्जेक्ट जोड़ने (एनएसएमयूटेबलएरे) की तरह पहले ऑटोरेलीज़ को कॉल करने के लिए यह ठीक है (और अनुशंसित) है? या इसे इसे जोड़ने के बाद इसे स्पष्ट रूप से जारी करना चाहिए। (मैं जानता हूँ कि NSMutableArray willl वस्तु बनाए रखने)

यह मेरे प्रश्नों का दिखाता है:

परिदृश्य ए (autorelease):

- (void) add { 
    // array is an instance of NSMutableArray 

    MyClass *obj = [[[MyClass alloc] init] autorelease]; 

    [array addObject:obj]; 
} 

परिदृश्य बी (स्पष्ट विज्ञप्ति):

- (void) add { 
    // array is an instance of NSMutableArray 

    MyClass *obj = [[MyClass alloc] init]; 

    [array addObject:obj]; 

    [obj release]; 
} 

मुझे लगता है कि दोनों सही हैं, लेकिन मुझे यकीन नहीं है, और मुझे यकीन नहीं है कि preffered तरीका क्या है।

क्या उद्देश्य-सी गुरु इस पर कुछ प्रकाश डाल सकते हैं?

उत्तर

7

दोनों सही हैं और काम करेंगे क्योंकि आप उन्हें उम्मीद कर रहे हैं।

मैं व्यक्तिगत रूप से बाद की विधि का उपयोग करना पसंद करता हूं, लेकिन केवल इसलिए कि जब वस्तुएं जारी की जाती हैं तो मुझे स्पष्ट होना पसंद है। ऑब्जेक्ट को ऑटोरेलेज़ करके, हम जो भी कर रहे हैं वह कह रहा है "यह ऑब्जेक्ट भविष्य में कुछ मनमानी बिंदु पर रिलीज़ हो जाएगा।" इसका मतलब है कि आप ऑटोरेलेज्ड ऑब्जेक्ट को सरणी में डाल सकते हैं, सरणी को नष्ट कर सकते हैं, और ऑब्जेक्ट शायद (संभवतः) मौजूद हो सकता है।

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

+2

यदि आप चाहते हैं कि आपका कोड पूरी तरह से सुरक्षित हो, तो इसे ऑटोरेलीज़ का उपयोग करने की दृढ़ता से अनुशंसा की जाती है: http://stackoverflow.com/questions/1147785/use-autorelease-before-adding-objects-to-a-collection/1149040#1149040 देखें – Casebash

3

वे दोनों सही हैं लेकिन बी को प्राथमिकता दी जा सकती है क्योंकि इसका कोई ओवरहेड नहीं है। Autorelease ऑटोरिज़ पूल को ऑब्जेक्ट का प्रभार लेने का कारण बनता है। इसमें बहुत ही मामूली ओवरहेड है, जो निश्चित रूप से शामिल वस्तुओं की संख्या से गुणा हो जाता है।

तो एक ऑब्जेक्ट ए और बी के साथ समान या कम हैं, लेकिन निश्चित रूप से ए में जोड़ने के लिए कई ऑब्जेक्ट्स वाले परिदृश्यों में ए का उपयोग नहीं करते हैं।

विभिन्न परिस्थितियों में ऑटोरेलीज़िंग देरी के अंत में कई ऑब्जेक्ट्स को मुक्त करने में देरी कर सकती है और जमा कर सकती है। यह उप-इष्टतम हो सकता है। ध्यान रखें कि वैसे भी ऑटोरेलीज़िंग स्पष्ट हस्तक्षेप के बिना बहुत कुछ होता है।

return [[myObject retain] autorelease]; 

इसलिए जब भी आप गेटर फोन आप autorelease पूल के लिए एक वस्तु जोड़ें: उदाहरण के लिए कई टिककर खेल इस तरह से लागू किया जाता है।

+0

"autorelease autorelease पूल वस्तु का प्रभार लेने के लिए कारण बनता है। " यह गलत है। ऑटोरेलीज पूल देरी संदेश सुविधा से ज्यादा कुछ नहीं है। ऑटोरेलीज पूल किसी ऑब्जेक्ट का "चार्ज नहीं लेता" है, यह केवल भविष्य में एक संदेश भेजने के लिए सूचीबद्ध करता है। – NSResponder

+0

"चार्ज ले लो" के साथ मेरा मतलब बिल्कुल था। मेरा जन्म यूरोपीय संघ में हुआ था लेकिन यूके में नहीं, मेरी गलती। – IlDan

0

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

http://macdevcenter.com/pub/a/mac/2001/07/27/cocoa.html?page=last&x-showcontent=text

+0

डाउनवोट के लिए कोई विशेष कारण? –

0

आप alloc है 'वस्तु एड, तो यह कुछ बिंदु पर इसे जारी करने के लिए अपने काम है। दोनों कोड स्निपेट autorelease के साथ शक्तिशाली रूप से धीमे समकक्ष होने के साथ ही वही, सही तरीका काम करते हैं।

व्यक्तिगत रूप से बोलते हुए, मैं autorelease रास्ता पसंद करता हूं, क्योंकि यह टाइप करना आसान है और लगभग कभी भी बाधा नहीं है।

0

वे दोनों ठीक हैं। कुछ लोग आपको "ओवरहेड" या ऐसी कुछ चीज़ों के कारण ऑटोरेलीज़ से बचने के लिए कहेंगे, लेकिन सच्चाई यह है कि व्यावहारिक रूप से कोई उपर नहीं है। आगे बढ़ें और इसे बेंचमार्क करें और "ओवरहेड" ढूंढने का प्रयास करें। आईफोन पर स्मृति की भूख की स्थिति में आप इसे टालने का एकमात्र कारण है। ओएस एक्स पर, आपके पास व्यावहारिक रूप से असीमित स्मृति है, इसलिए यह बहुत अंतर नहीं ले रहा है। बस जो भी आपके लिए सबसे सुविधाजनक है उसका उपयोग करें।

+1

यह उतना ही कट-एंड-सूखे नहीं है। यदि ऑब्जेक्ट्स को लूप में ऑटोरेलेज्ड किया जा रहा है, तो संभव है कि बड़ी संख्या में अतिरिक्त ऑब्जेक्ट्स को तब तक छोड़ दिया जा सके जब तक एक संलग्न ऑटोरेलीज पूल निकाला न जाए। यह कभी-कभी बड़ी मेमोरी ओवरहेड और मंदी का कारण बन सकता है। (हाँ, यह मेरे साथ हुआ है।) हालांकि यह सामान्य नहीं है। आम तौर पर जब तक ऐसा होता है तब तक आप इस मुद्दे को अनदेखा कर सकते हैं, और उसके बाद लूप में क्या हो रहा है और स्पष्ट रिलीज़ का उपयोग करके इसे अनुकूलित करें। –

+1

जो कुछ आवश्यक है वह ऑटोरेलीज पूल का विशेष प्रबंधन है। इसका अभी भी मतलब यह नहीं है कि ऑटोरेलीज एक बुरी चीज है, खासकर सामान्य मामले में नहीं। – Chuck

11

आईएमएचओ, जिस तरह से 'दाएं' वरीयता का विषय है। मैं ऐसे उत्तरदाताओं से असहमत नहीं हूं जो autorelease का उपयोग न करने का समर्थन करते हैं, लेकिन मेरी प्राथमिकता autorelease का उपयोग करना है जब तक कि एक अत्यधिक अनिवार्य कारण न हो। मैं अपने कारणों की सूची दूंगा और आप यह तय कर सकते हैं कि प्रोग्रामिंग की आपकी शैली के लिए उपयुक्त है या नहीं।

चक ने बताया कि अर्द्ध शहरी किंवदंती है कि ऑटोरेलीज पूल का उपयोग करने के लिए कुछ प्रकार का ओवरहेड है। यह सच्चाई से आगे नहीं हो सकता है, और यह कोड के प्रदर्शन के आखिरी बिट को निचोड़ने के लिए शार्क.एप का उपयोग करके अनगिनत घंटे से आता है। इसके लिए अनुकूलित करने का प्रयास करना "समयपूर्व अनुकूलन" क्षेत्र में गहरा है। यदि, और केवल तभी, शार्क.एप आपको कठिन डेटा देता है कि यह एक समस्या हो सकती है, आपको इसे देखने पर भी विचार करना चाहिए।

जैसा कि अन्य ने बताया, एक ऑटोरेलेज्ड ऑब्जेक्ट "बाद के बिंदु पर जारी किया गया" है। इसका मतलब यह है कि जब तक कि "बाद का बिंदु" चारों ओर घूमता है, तब तक वे स्मृति को ऊपर ले जाते हैं। "अधिकांश" मामलों के लिए, यह एक घटना प्रसंस्करण पास के निचले हिस्से में है जब रन लूप अगली घटना (टाइमर, उपयोगकर्ता कुछ क्लिक करना आदि) तक सो जाता है।

कभी-कभी, आपको बाद में, उन अस्थायी वस्तुओं से जल्द से जल्द छुटकारा पाना होगा। उदाहरण के लिए, आपको एक विशाल, बहु-मेगाबाइट फ़ाइल, या डेटाबेस से हजारों पंक्तियों को संसाधित करने की आवश्यकता है। जब ऐसा होता है, तो आपको एक अच्छी तरह से चुने गए बिंदु पर NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; रखना होगा, इसके बाद नीचे [pool release]; होगा। यह लगभग हमेशा किसी प्रकार के "लूप बैच प्रोसेसिंग" में होता है, इसलिए यह आमतौर पर कुछ महत्वपूर्ण पाश के प्रारंभ और नीचे होता है। फिर, यह साक्ष्य आधारित होना चाहिए, न कि आधारित आधारित। Instrument.app का ऑब्जेक्टऑलोक वह है जो आप इन परेशानियों को खोजने के लिए उपयोग करते हैं।

मुख्य कारण मैं autoreleaserelease करना पसंद करते हैं, हालांकि, यह ज्यादा आसान रिसाव से मुक्त कार्यक्रमों लिखने के लिए है। संक्षेप में, यदि आप release मार्ग जाने के लिए चुनते हैं, तो आप गारंटी कि release अंततः सभी परिस्थितियों में, obj को भेजा जाता है की जरूरत है। हालांकि ऐसा लगता है कि यह आसान हो सकता है, वास्तव में अभ्यास में करना आश्चर्यजनक रूप से कठिन है। अपने उदाहरण लें, उदाहरण के लिए: कुछ

// array is an instance of NSMutableArray 
    MyClass *obj = [[MyClass alloc] init]; 
    [array addObject:obj]; 
    // Assume a few more lines of work.... 
    [obj release]; 

अब किसी कारण से कल्पना करो कि, कहीं, आसानी से अपने धारणा है कि array शायद परिणामों पर कार्रवाई करने के कुछ विधि का उपयोग कर के परिणाम के रूप परिवर्तनशील है, उल्लंघन होता है और लौट आए संसाधित परिणाम वाले सरणी को NSArray के रूप में बनाया गया था।जब आप addObject: को उस अपरिवर्तनीय NSArray पर भेजते हैं, तो एक अपवाद फेंक दिया जाएगा, और आप obj को release संदेश कभी नहीं भेजेंगे। या हो सकता है कुछ के बीच जब objalloc घ था और release करने के लिए आवश्यक कॉल, जैसे आप गलती से तुरंत कुछ की हालत और return() जाँच क्योंकि यह अपने मन फिसल गया है कि release करने के लिए कि कॉल पर बाद में होनी चाहिए कहीं गलत हो जाता है।

आपने अभी एक वस्तु लीक की है। और शायद यह पता लगाने की कोशिश करने के कई दिनों तक खुद को साइन अप करें कि यह कहां और क्यों लीक हो रहा है। अनुभव से, आप ऊपर दिए गए कोड को देखकर कई घंटे व्यतीत करेंगे, यह आश्वस्त है कि यह संभवतः रिसाव का स्रोत नहीं हो सकता है क्योंकि आप objrelease भेजते हैं। फिर, कई दिनों के बाद, आप अनुभव करेंगे कि केवल एक धार्मिक epiphany के रूप में वर्णित किया जा सकता है क्योंकि आप समस्या के कारण के लिए प्रबुद्ध हैं।

// array is an instance of NSMutableArray 
    MyClass *obj = [[[MyClass alloc] init] autorelease]; 
    [array addObject:obj]; 
    // Assume a few more lines of work.... 

अब, यह नहीं रह गया है कि क्या होता है, क्योंकि यह गलती से obj लीक करने के लिए लगभग असंभव है, यहां तक ​​कि अत्यंत असामान्य या असाधारण कोने मामलों के तहत मायने रखती है:

autorelease मामले पर विचार करें।

+0

यह मेरे नए प्रश्न में यहां आया: http://stackoverflow.com/questions/2911678। महान बिंदु। –

+1

'[पूल नाली] 'मामले में बेहतर विकल्प की तरह प्रतीत होता है कि आईओएस को कभी भी जीसी मिलती है –

0

मैं ब्रोविटी और "सुरक्षा" के लिए ए (ऑटोरेलीज़िंग) पसंद करता हूं, क्योंकि जॉन इसे कॉल करता है। यह मेरे कोड को सरल बनाता है, और मैंने कभी इसके साथ समस्याओं में भाग नहीं लिया है।

यह आज तक है: मुझे एक सरणी में जोड़ने से पहले ब्लॉक को ऑटोरेलेज़ करने में कोई समस्या थी। मेरी stackoverflow प्रश्न देखें: [myArray addObject:[[objcBlock copy] autorelease]] crashes on dealloc'ing the array (अद्यतन: बाहर कर देता है समस्या मेरी कोड में कहीं और था, लेकिन अभी भी, वहाँ autorelease साथ व्यवहार में एक सूक्ष्म अंतर ... था)

संबंधित मुद्दे