2009-08-02 12 views
25

मैं स्मृति प्रबंधित कोड में नया हूं लेकिन मुझे विचार बहुत अच्छी तरह से मिलता है।उद्देश्य सी रिलीज, ऑटोरेलीज, और डेटा प्रकार

XCode में लीक उपकरण के माध्यम से अपने एप्लिकेशन लेने पर, मैंने देखा मैं सिर्फ अपने कस्टम वस्तुओं को साफ करने के लिए किया था, लेकिन नहीं गतिशील रूप से उदाहरण के लिए सरणियों बनाया, तो मैं समझ उन डेटा प्रकार autoreleased कर रहे हैं - समझ में आता है के बाद से मैं केवल था उन सरणी को रिलीज़ करने के लिए जिन्हें मैंने उन गुणों के रूप में उपयोग किया था जिन पर एक (बनाए रखा) था। मैं एक निश्चित सरणी इस तरह प्रारंभ पर एक रिसाव हो रही थी:

तो मैं कुछ अजीब देखा

NSMutableArray *removals = [NSMutableArray new]; 

नहीं बल्कि एक ऐसी ही एक

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:9]; 

अब, कारण एक स्थापित किया गया था "नया" यह है कि इसमें 0-99 आइटम हो सकते हैं, जबकि दूसरा मुझे पता था कि 9 हमेशा होने वाला था। चूंकि दोनों एरे बाद में एक ही विधि में पास हो जाते हैं, उपयोगकर्ता इंटरैक्शन के आधार पर, मुझे या तो रिसाव मिल रहा था अगर मैंने विधि के अंत में रिलीज़ नहीं किया, या अपवाद अगर मैंने किया!

मैं

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99]; 

को पहली सरणी बदल गया है और मेरे पास कोई लीक हो जाते हैं और कुछ भी रिलीज करने के लिए नहीं है। क्या कोई समझा सकता है?

उत्तर

65

memory management rules में बताया गया है, तो आप एक उद्देश्य यह है कि आप के साथ बनाया है, जब भी +alloc, +new, -copy, या -mutableCopy, वह आपका ही है और कुछ बिंदु पर इसे जारी करने के लिए जिम्मेदार हैं। (वास्तव में, +new[[MyClass alloc] init] के लिए सिर्फ लघुरूप है।) जैसा कि आपने नोट किया है, इसे जारी किए बिना [NSArray new] के माध्यम से एक सरणी बनाना एक स्मृति रिसाव है।हालांकि, अगर आप इस ऑब्जेक्ट को सही तरीके से संभालते हैं, तो आमतौर पर इसे किसी बिंदु पर रिलीज़ करना संभव होता है। उदाहरण के लिए:

  • तो विधि है कि का उपयोग करता सरणी से विधि है कि सरणी बनाता है के भीतर भी कहा जाता है, तो आप सरणी जारी करने के लिए यह प्रयोग किया गया है के बाद सक्षम होना चाहिए। यदि आंतरिक विधि को सरणी के चारों ओर एक और स्थायी संदर्भ रखने की आवश्यकता है, तो वह विधि -retain और अंततः -release ऑब्जेक्ट भेजने के लिए ज़िम्मेदार है।

    - (void)myMethod { 
        NSArray *removals = [NSArray new]; 
        // ... 
        [someObject someOtherMethod:removals]; 
        [removals release]; 
    } 
    
  • आप एक वस्तु के लिए एक -init विधि में सरणी बनाया है, तो -dealloc विधि इसे जारी कर सकते हैं जब वस्तु नष्ट हो जाता है: उदाहरण के लिए।

  • आप सरणी बनाने की जरूरत है और फिर विधि से वापसी यह, तुम कारण यह है कि autoreleasing आविष्कार किया गया था की खोज की है, तो। ऑब्जेक्ट को जारी करने के लिए आपकी विधि का कॉलर ज़िम्मेदार नहीं है, क्योंकि यह +alloc, +new, -copy, या -mutableCopy विधि नहीं है, लेकिन आपको यह सुनिश्चित करना होगा कि यह अंततः जारी हो जाए। इस मामले में, आप इसे वापस करने से पहले ऑब्जेक्ट पर -autorelease मैन्युअल रूप से कॉल करते हैं। उदाहरण के लिए:

    - (NSArray *)myMethod { 
        NSArray *removals = [NSArray new]; 
        // ... 
        return [removals autorelease]; 
    } 
    

जब आप +arrayWithCapacity: के माध्यम से सरणी, आप "विशेष" तरीकों में से एक बुला नहीं कर रहे हैं, तो आप परिणाम जारी करने के लिए की जरूरत नहीं है बनाते हैं। यह शायद -autorelease के साथ लागू किया गया है, जो उपरोक्त अंतिम उदाहरण की तरह है, लेकिन जरूरी नहीं है। (संयोग से, आप [NSMutableArray array] के साथ एक खाली ऑटोरेलेस्ड एनएसएमयूटेबलएरे भी बना सकते हैं; विधि एनएसएआरएआरई में पाई जाती है, इसलिए यह एनएसएमयूटेबलएरे के तहत प्रलेखन में दिखाई नहीं देगी, लेकिन यह एनएसएमयूटेबलएरे क्लास को भेजे जाने पर एक परिवर्तनीय सरणी बनायेगी।) यदि आप अपनी विधि से सरणी वापस करने जा रहे हैं, आप इसे [[[NSMutableArray alloc] init] autorelease] के लिए शॉर्टेंड के रूप में उपयोग कर सकते हैं-लेकिन यह सिर्फ एक शॉर्टकट है। कई परिस्थितियों में, हालांकि, आप -init या +new के साथ ऑब्जेक्ट बना सकते हैं और इसे उचित समय पर मैन्युअल रूप से रिलीज़ कर सकते हैं।

+(NSMutableArray*) new 
{ 
    return [[NSMutableArray alloc] init]; 
} 

और

+(NSMutableArray*) arrayWithCapacity:(NSNumber)capacity 
{ 
    return [[NSMutableArray alloc] initWithCapacity:capacity] **autorelease**]; 
} 

पहले मामले में सरणी केवल आवंटित किया जाता है और आप जिम्मेदार हैं यह de-आवंटन:

4

कोको कुछ नामकरण सम्मेलनों का उपयोग करता है। कुछ भी जो आवंटन, नया, या प्रतिलिपि से शुरू होता है, एक को बनाए रखने के साथ कुछ देता है 1 और आपको रिलीज़ करने की आवश्यकता होती है। फ़ंक्शन रिटर्न में कुछ भी संतुलित संतुलन होता है (यह किसी और चीज द्वारा आयोजित किया जा सकता है, या इसे बरकरार रखा जा सकता है)।

तो:

NSMutableArray *removals = [NSMutableArray new]; 

1 के एक retainCount है, और:

NSMutableArray *removals = [NSMutableArray arrayWithCapacity:99]; 

या

NSMutableArray *removals = [NSMutableArray array]; 

के बाद से तरीकों alloc, नए या उपसर्ग के साथ नहीं कर रहे हैं मत करो प्रति। यह सब स्मृति प्रबंधन documentation में लिखा गया है। विशेष रूप से:

आप एक वस्तु का स्वामित्व लेने के लिए यदि आप यह एक तरीका है जिसका नाम "alloc" या "नया" के साथ शुरू होता या "कॉपी" शामिल हैं (उदाहरण के लिए, alloc, newObject का उपयोग कर बनाने के लिए, या mutableCopy), या यदि आप इसे एक सतत संदेश भेजें। को रिलीज़ या ऑटोरेलीज़ का उपयोग करके आपके स्वामित्व वाली वस्तुओं के स्वामित्व को छोड़ने के लिए ज़िम्मेदार हैं। कोई अन्य समय आपको एक ऑब्जेक्ट प्राप्त होता है, आपको इसे रिलीज़ नहीं करना चाहिए।

+1

** उन सभी विधियों में से एक ** एक वस्तु को 1 की रखरखाव के साथ वापस कर देता है। अंतर यह है कि कुछ के साथ आप ऑब्जेक्ट का स्वामी हैं और इस प्रकार इसे रिलीज़ करने की आवश्यकता है, और दूसरों के साथ आपके पास नहीं है ऑब्जेक्ट और इसे रिलीज़ करने की आवश्यकता नहीं है (लेकिन वर्तमान कॉल श्रृंखला के आसपास होने पर भी इसकी गणना नहीं हो सकती है)। – Chuck

+2

कड़ाई से बोलते हुए, नहीं, वे एक कार्यान्वयन विस्तार नहीं करते हैं। कई मामलों में वे अलग-अलग रखरखाव की गणना के साथ चीजें वापस कर देते हैं। उदाहरण के लिए = [UIImage imageNamed:] कुछ बड़े बड़े रखरखाव के साथ कुछ वापस कर सकता है क्योंकि यह एक कैश की गई छवि का पुन: उपयोग कर सकता है। –

+1

ठीक है, हां, बरकरार गिनती ही एक कार्यान्वयन विस्तार है। ऐप्पल के दस्तावेज़ जितना कहते हैं। और ओएस एक्स के मौजूदा संस्करणों पर, ऊपर सूचीबद्ध सभी मामलों में, इस कार्यान्वयन के विवरण का मूल्य 1. – Chuck

7

यह कैसे चीजें दृश्य के पीछे लागू किया है। इसके विपरीत सरणी WithCapacity आपके लिए autoreleased है और रिसाव का कारण नहीं होगा आप भी deallocate भूलना भूल जाते हैं।

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