कोको और उद्देश्य-सी के साथ संदर्भ गिनती को समझना


122

मैं अभी अभी iPhone SDK के साथ खेलने के उद्देश्य से ऑब्जेक्टिव-सी और कोको पर एक नजर डाल रहा हूं। मैं सी की अवधारणा mallocऔर freeअवधारणा के साथ काफी सहज हूं , लेकिन कोको की संदर्भ गणना योजना ने मुझे भ्रमित कर दिया है। मुझे बताया गया है कि आप इसे समझने के बाद एक बार बहुत ही सुंदर हैं, लेकिन मैं अभी तक कूबड़ के ऊपर नहीं हूं।

कैसे करते हैं release, retainऔर autoreleaseकाम करते हैं और उनके उपयोग के बारे में क्या धारणाएं हैं?

(या इसमें असफल होकर, आपने क्या पढ़ा जो आपको इसे पाने में मदद मिली?)

जवाबों:


148

चलो शुरू करते हैं retainऔर release; autoreleaseमूल अवधारणाओं को समझने के बाद वास्तव में सिर्फ एक विशेष मामला है।

कोको में, प्रत्येक वस्तु इस बात का ट्रैक रखती है कि उसे कितनी बार संदर्भित किया जा रहा है (विशेषकर, NSObjectबेस क्लास इसे लागू करता है)। retainकिसी ऑब्जेक्ट पर कॉल करके , आप यह बता रहे हैं कि आप इसकी संदर्भ संख्या एक से बढ़ाना चाहते हैं। कॉल करके release, आप उस ऑब्जेक्ट को बताते हैं जिसे आप इसे जाने दे रहे हैं, और इसकी संदर्भ संख्या को घटाया गया है। यदि, कॉल करने के बाद release, संदर्भ गणना अब शून्य है, तो उस ऑब्जेक्ट की मेमोरी सिस्टम द्वारा मुक्त हो जाती है।

मूल तरीका इससे भिन्न होता है mallocऔर freeयह है कि किसी भी दिए गए ऑब्जेक्ट को सिस्टम के अन्य हिस्सों के दुर्घटनाग्रस्त होने के बारे में चिंता करने की आवश्यकता नहीं है क्योंकि आपने उपयोग की गई मेमोरी को मुक्त कर दिया है। यह मानते हुए कि हर कोई नियमों के अनुसार खेल रहा है और बनाए रख रहा है / जारी कर रहा है, जब कोड का एक टुकड़ा बनाए रखता है और फिर ऑब्जेक्ट को रिलीज़ करता है, तो कोड का कोई अन्य टुकड़ा भी संदर्भित करता है और ऑब्जेक्ट अप्रभावित रहेगा।

जो कभी-कभी भ्रमित हो सकता है वह उन परिस्थितियों को जान रहा है जिनके तहत आपको कॉल करना चाहिए retainऔर release। मेरे अंगूठे का सामान्य नियम यह है कि अगर मैं किसी वस्तु को कुछ समय के लिए लटकाना चाहता हूं (यदि यह किसी वर्ग में सदस्य चर है, उदाहरण के लिए), तो मुझे यह सुनिश्चित करने की आवश्यकता है कि वस्तु का संदर्भ गणना मेरे बारे में जानता है। जैसा कि ऊपर वर्णित है, किसी ऑब्जेक्ट की संदर्भ गणना को कॉल करके बढ़ाया जाता है retain। कन्वेंशन द्वारा, यह भी बढ़े हुए (1, वास्तव में) सेट किया जाता है, जब ऑब्जेक्ट "इनिट" विधि के साथ बनाया जाता है। इन मामलों में से किसी में, releaseजब मैं इसके साथ किया जाता है, तो वस्तु पर कॉल करना मेरी जिम्मेदारी है। अगर मैं नहीं करता हूं, तो स्मृति रिसाव होगा।

वस्तु निर्माण का उदाहरण:

NSString* s = [[NSString alloc] init];  // Ref count is 1
[s retain];                             // Ref count is 2 - silly
                                        //   to do this after init
[s release];                            // Ref count is back to 1
[s release];                            // Ref count is 0, object is freed

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

यह ध्यान रखना महत्वपूर्ण है कि (फिर, सम्मेलन द्वारा) सभी ऑब्जेक्ट निर्माण वर्ग विधियाँ एक ऑटोरेल्ड ऑब्जेक्ट लौटाती हैं। उदाहरण के लिए, निम्नलिखित उदाहरण में, चर "s" में 1 की संदर्भ संख्या है, लेकिन इवेंट लूप के पूरा होने के बाद, यह नष्ट हो जाएगा।

NSString* s = [NSString stringWithString:@"Hello World"];

यदि आप उस स्ट्रिंग को लटकाना चाहते हैं, तो आपको retainस्पष्ट रूप से कॉल करने की आवश्यकता होगी , और releaseजब आप काम कर रहे हों तब इसे स्पष्ट रूप से करें ।

निम्नलिखित कोड पर विचार करें (बहुत अधिक वंचित), और आपको एक ऐसी स्थिति दिखाई देगी, जहां autoreleaseआवश्यक है:

- (NSString*)createHelloWorldString
{
    NSString* s = [[NSString alloc] initWithString:@"Hello World"];

    // Now what?  We want to return s, but we've upped its reference count.
    // The caller shouldn't be responsible for releasing it, since we're the
    // ones that created it.  If we call release, however, the reference 
    // count will hit zero and bad memory will be returned to the caller.  
    // The answer is to call autorelease before returning the string.  By 
    // explicitly calling autorelease, we pass the responsibility for
    // releasing the string on to the thread's NSAutoreleasePool, which will
    // happen at some later time.  The consequence is that the returned string 
    // will still be valid for the caller of this function.
    return [s autorelease];
}

मुझे लगता है कि यह सब थोड़ा भ्रमित करने वाला है - कुछ बिंदु पर, हालांकि, यह क्लिक करेगा। यहां आपको जाने के लिए कुछ संदर्भ दिए गए हैं:


8
आपने लिखा है: "ऑटोरेलिज को बुलाकर, हम अस्थायी रूप से संदर्भ गणना को टक्कर देते हैं"। मुझे लगता है कि यह गलत है; autorelease केवल भविष्य में जारी की जाने वाली वस्तु को चिह्नित करता है, यह Ref count को नहीं बढ़ाता है: cocoadev.com/index.pl?AutoRelease
LKM

2
"अब ऑटोरेलिज़ के लिए। ऑटोरेलिज़ को एक सुविधाजनक (और कभी-कभी आवश्यक) तरीके के रूप में इस्तेमाल किया जाता है ताकि सिस्टम को इस वस्तु को थोड़ी देर बाद मुक्त करने के लिए कहा जा सके।" लीड-इन वाक्य के रूप में, यह गलत है। यह सिस्टम को "फ्री [इट] अप" करने के लिए नहीं कहता है, यह इसे रिटेन काउंट को बढ़ाने के लिए कहता है।
mmalc

3
अच्छी व्याख्या के लिए बहुत बहुत धन्यवाद। बस एक चीज जो अभी भी अस्पष्ट है। यदि NSString* s = [[NSString alloc] initWithString:@"Hello World"];एक ऑटोरेल्ड ऑब्जेक्ट लौटाता है (जैसा कि आप इसे लिखते हैं) तो मुझे फिर से क्यों करना है return [s autorelease];और इसे "ऑटोरेलिज़" सेट करना है और न कि बस return s?
znq

3
@ सेफ़ान: [[NSString alloc] initWithString:@"Hello World"]एक ऑटोरेल्ड ऑब्जेक्ट वापस नहीं करेगा। जब भी allocबुलाया जाता है, तो संदर्भ संख्या 1 पर सेट की जाती है, और यह सुनिश्चित करने के लिए उस कोड की जिम्मेदारी होती है कि वह रिलीज़ हो जाए। [NSString stringWithString:]कॉल, दूसरे हाथ पर, है एक autoreleased वस्तु लौटने।
मैट डिलार्ड

6
मज़ा सामान्य ज्ञान: चूंकि उत्तर @ "और NSString का उपयोग करता है, तार पूरे भर में स्थिर होते हैं और इस प्रकार, पूर्ण बनाए रखने की गिनती दोनों निरंतर और पूरी तरह से अप्रासंगिक हो जाएगी .... किसी भी तरह से उत्तर को गलत नहीं बनाता है, बस इस तथ्य को पुष्ट करता है कि पूर्ण रूप से बनाए रखने की गिनती वास्तव में कभी ऐसी चीज नहीं है जिसके बारे में आपको चिंता करनी चाहिए।
bbum

10

यदि आप इसे बनाए रखने / जारी करने की प्रक्रिया को समझते हैं तो दो सुनहरा नियम हैं जो कोको प्रोग्रामर को स्थापित करने के लिए "डुह" स्पष्ट हैं, लेकिन दुर्भाग्य से नए लोगों के लिए यह स्पष्ट रूप से स्पष्ट नहीं है।

  1. यदि कोई फ़ंक्शन जो किसी ऑब्जेक्ट को वापस करता है alloc, createया copyउसके नाम पर है तो ऑब्जेक्ट आपका है। [object release]जब आप इसे पूरा कर लें तो आपको कॉल करना होगा । या CFRelease(object), अगर यह एक कोर-फाउंडेशन ऑब्जेक्ट है।

  2. यदि इसके नाम में इनमें से एक भी शब्द नहीं है तो वस्तु किसी और की है। [object retain]यदि आप अपने फ़ंक्शन के अंत के बाद ऑब्जेक्ट रखना चाहते हैं तो आपको कॉल करना होगा ।

आप अपने द्वारा बनाए गए कार्यों में भी इस सम्मेलन का पालन करेंगे।

(नाइटपिकर: हां, दुर्भाग्य से कुछ एपीआई कॉल हैं जो इन नियमों के अपवाद हैं लेकिन वे दुर्लभ हैं)।


11
यह अधूरा और गलत है। मैं यह समझने में विफल रहता हूं कि लोग प्रासंगिक दस्तावेज की ओर संकेत करने के बजाय नियमों को दोहराने की कोशिश क्यों करते हैं: developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/…
mmalc

4
विशेष रूप से कोर फाउंडेशन के नियम कोको से भिन्न हैं; डेवलपर
।apple.com

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

1
माफ़ करना! मुझे लगता है कि मैं वोटिंग में जल्दबाजी कर रहा था। स्मृति प्रबंधन नियम आपका उत्तर लगभग सेब डॉक का उद्धरण देता है।
सैम

8

यदि आप डेस्कटॉप के लिए कोड लिख रहे हैं और आप मैक ओएस एक्स 10.5 को लक्षित कर सकते हैं, तो आपको कम से कम ऑब्जेक्टिव-सी कचरा संग्रह का उपयोग करना चाहिए। यह वास्तव में आपके अधिकांश विकास को सरल करेगा - यही कारण है कि ऐप्पल ने इसे पहले स्थान पर बनाने और इसे अच्छा प्रदर्शन करने के लिए सभी प्रयास किए।

जीसी का उपयोग नहीं करने पर स्मृति प्रबंधन नियमों के लिए:

  • आप का उपयोग कर एक नई वस्तु बनाने हैं +alloc/+allocWithZone:, +new, -copyया -mutableCopyया यदि आप -retainएक वस्तु है, आप इसे का स्वामित्व ले जा रहे हैं और यह सुनिश्चित करना चाहिए यह भेजा जाता है-release
  • यदि आपको किसी अन्य तरीके से कोई वस्तु मिलती है, तो आप उसके मालिक नहीं हैं और यह सुनिश्चित नहीं किया जाना चाहिए कि यह भेजा गया है-release
  • यदि आप यह सुनिश्चित करना चाहते हैं कि कोई वस्तु भेजी जाए -releaseतो आप या तो स्वयं भेज सकते हैं, या आप वस्तु भेज सकते हैं -autoreleaseऔर वर्तमान ऑटोरेलिज पूल-release ( -autoreleaseसूखा प्राप्त होने पर ) एक बार भेज देगा ।

आमतौर पर -autoreleaseयह सुनिश्चित करने के एक तरीके के रूप में उपयोग किया जाता है कि वस्तुएं वर्तमान घटना की लंबाई के लिए रहती हैं, लेकिन बाद में साफ हो जाती हैं, क्योंकि एक ऑटोरेलिज पूल है जो कोको के घटना प्रसंस्करण के चारों ओर है। कोको में, यह है अब तक एक फोन करने वाले की तुलना में यह है कि फोन करने वाले खुद को रिहा करने की जरूरत है objets वापस जाने के लिए है autoreleased कर रहे हैं कि करने के लिए वस्तुओं वापस जाने के लिए और अधिक सामान्य।


6

ऑब्जेक्टिव-सी रेफरेंस काउंटिंग का उपयोग करता है , जिसका अर्थ है कि प्रत्येक ऑब्जेक्ट का एक रेफरेंस काउंट है। जब कोई वस्तु बनाई जाती है, तो उसमें "1" की संदर्भ संख्या होती है। सीधे शब्दों में, जब किसी ऑब्जेक्ट को संदर्भित किया जाता है (यानी, कहीं संग्रहीत किया जाता है), तो उसे "बनाए रखा जाता है" जिसका अर्थ है कि उसकी संदर्भ संख्या एक से बढ़ जाती है। जब किसी वस्तु की आवश्यकता नहीं रह जाती है, तो इसे "जारी" किया जाता है, जिसका अर्थ है कि इसकी संदर्भ संख्या एक से कम हो जाती है।

जब किसी ऑब्जेक्ट की संदर्भ संख्या 0 होती है, तो ऑब्जेक्ट को मुक्त कर दिया जाता है। यह मूल संदर्भ गिनती है।

कुछ भाषाओं के लिए, संदर्भ स्वचालित रूप से बढ़े और घटे हैं, लेकिन उद्देश्य-सी उन भाषाओं में से एक नहीं है। इस प्रकार प्रोग्रामर को बनाए रखने और जारी करने के लिए जिम्मेदार है।

एक विधि लिखने का एक विशिष्ट तरीका है:

id myVar = [someObject someMessage];
.... do something ....;
[myVar release];
return someValue;

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

जब किसी ऑब्जेक्ट को "ऑटोरेलिज़" संदेश भेजा जाता है, तो ऑब्जेक्ट इस वर्तमान थ्रेड के लिए स्टैक पर बैठे किसी भी ऑटोरेलिज़ पूल की तलाश करेगा। यह सूची में ऑब्जेक्ट को भविष्य में कुछ बिंदु पर "रिलीज़" संदेश भेजने के लिए ऑब्जेक्ट के रूप में जोड़ देगा, जो कि आम तौर पर तब होता है जब पूल स्वयं जारी होता है।

ऊपर दिए गए कोड को लेते हुए, आप इसे छोटा होने के लिए फिर से लिख सकते हैं और कहकर पढ़ने में आसान हो सकते हैं:

id myVar = [[someObject someMessage] autorelease];
... do something ...;
return someValue;

क्योंकि ऑब्जेक्ट ऑटोरिल्ड है, हमें अब उस पर स्पष्ट रूप से "रिलीज़" कॉल करने की आवश्यकता नहीं है। ऐसा इसलिए है क्योंकि हम जानते हैं कि कुछ ऑटोरेलिज़ पूल बाद में हमारे लिए करेंगे।

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


2
यह सिर्फ गलत है। दिखाए गए दोनों उदाहरणों में कुछ ऑबजेक्ट रिलीज़ या ऑटोरलेज़ भेजने की आवश्यकता नहीं है।
एमएमएलसी

6

यहोशू (# 6591) - मैक ओएस एक्स 10.5 में कचरा संग्रह सामान बहुत अच्छा लगता है, लेकिन आईफोन के लिए उपलब्ध नहीं है (या यदि आप चाहते हैं कि आपका ऐप मैक ओएस एक्स के पूर्व 10.5 संस्करण पर चले)।

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


2
जीसी और संदर्भ गिनती दोनों का समर्थन करने वाले संकर ढांचे को लिखना पूरी तरह से संभव है।
mmalc

6

हमेशा की तरह, जब लोग संदर्भ सामग्री को फिर से शब्द देने की कोशिश करने लगते हैं, तो वे लगभग हमेशा गलत हो जाते हैं या एक अधूरा विवरण प्रदान करते हैं।

Apple कोको के लिए मेमोरी मैनेजमेंट प्रोग्रामिंग गाइड में कोको की मेमोरी प्रबंधन प्रणाली का पूरा विवरण प्रदान करता है , जिसके अंत में मेमोरी प्रबंधन नियमों का एक संक्षिप्त लेकिन सटीक सारांश है ।



1
और सारांश नियमों के लिए: developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/…
माइकल बाल्टिक

2
वास्तव में यह एक बहुत बेहतर एकल-पृष्ठ सारांश है: developer.apple.com/mac/library/documentation/Cocoa/Conceptual/…
ब्रायन मोसकाउ

6

मैं $ 50 को छोड़ने और Hillegass पुस्तक प्राप्त करने के बारे में सोचना चाहूंगा, इसके अलावा मैं आपको बनाए रखने / जारी करने के विशिष्ट में नहीं जोड़ूंगा, लेकिन मैं आपके आवेदन के विकास में बहुत जल्दी इंस्ट्रूमेंट्स टूल का उपयोग करने का सुझाव दूंगा (यहां तक ​​कि आपका पेहला!)। ऐसा करने के लिए, रन-> प्रदर्शन टूल से शुरू करें। मैं लीक्स के साथ शुरू करूंगा जो कि उपलब्ध कई उपकरणों में से एक है, लेकिन जब आप रिलीज करना भूल गए हैं तो आपको दिखाने में मदद करेगा। यह चुनौतीपूर्ण है कि आपको कितनी जानकारी प्रस्तुत की जाएगी। लेकिन तेजी से उठने और जाने के लिए इस ट्यूटोरियल की जाँच करें:
COUTA TUTORIAL: FIXING MEMORY LEAKS withSTRUMENTS

वास्तव में लीक को मजबूर करने का एक बेहतर तरीका हो सकता है, बदले में, उन्हें रोकने के तरीके सीखना! सौभाग्य ;)


5

मैट डिलार्ड ने लिखा :

वापसी [[ऑटोरेलिज़] रिलीज];

Autorelease वस्तु को बनाए नहीं रखता है। ऑटोरेलेज़ ने इसे बाद में जारी करने के लिए कतार में रखा। आप वहाँ एक रिलीज़ स्टेटमेंट नहीं चाहते हैं।




4

NilObject का जवाब एक अच्छी शुरुआत है। यहां मैनुअल मेमोरी मैनेजमेंट ( iPhone पर आवश्यक ) से संबंधित कुछ पूरक जानकारी दी गई है

यदि आप व्यक्तिगत रूप से alloc/initएक वस्तु हैं, तो यह 1 के संदर्भ संख्या के साथ आता है। आप इसे साफ करने के लिए जिम्मेदार हैं जब इसकी आवश्यकता नहीं होती है, या तो कॉल करके [foo release]या[foo autorelease] । रिहाई इसे तुरंत दूर कर देती है, जबकि ऑटोरेलेज़ ऑब्जेक्ट को ऑटोरेलिज़ पूल में जोड़ता है, जो बाद में इसे स्वचालित रूप से जारी करेगा।

ऑटोरेल्ज़ मुख्य रूप से तब होता है जब आपके पास एक ऐसी विधि होती है, जिसमें प्रश्न में ऑब्जेक्ट को वापस करने की आवश्यकता होती है ( इसलिए आप इसे मैन्युअल रूप से जारी नहीं कर सकते हैं, अन्यथा आप एक शून्य ऑब्जेक्ट लौटा देंगे। ) लेकिन आप इसे या तो पकड़ना नहीं चाहते हैं, या तो ।

यदि आप ऐसी वस्तु प्राप्त करते हैं, जहाँ आपने इसे प्राप्त करने के लिए आबंटन / इनिट नहीं कहा है - उदाहरण के लिए:

foo = [NSString stringWithString:@"hello"];

लेकिन आप इस ऑब्जेक्ट को लटका देना चाहते हैं, आपको कॉल करना होगा [फू रिटेन]। अन्यथा, यह संभव है कि यह मिल जाएगा autoreleasedऔर आप एक शून्य संदर्भ पर पकड़ लेंगे (जैसा कि ऊपर के stringWithStringउदाहरण में होगा )। जब आपको इसकी आवश्यकता नहीं है, तो कॉल करें [foo release]


2

ऊपर दिए गए उत्तर स्पष्ट दस्तावेज के स्पष्ट प्रतिबंध देते हैं; समस्या ज्यादातर नए लोगों में चलती है, जो अनजाने मामलों में है। उदाहरण के लिए:

  • Autorelease : डॉक्स का कहना है कि यह "भविष्य में किसी बिंदु पर" एक रिलीज को ट्रिगर करेगा। कब?! मूल रूप से, आप तब तक ऑब्जेक्ट पर भरोसा कर सकते हैं जब तक आप सिस्टम कोड लूप में अपने कोड से बाहर नहीं निकल जाते। सिस्टम MAY वर्तमान घटना चक्र के बाद किसी भी समय ऑब्जेक्ट को जारी करता है। (मुझे लगता है कि मैट ने कहा कि, पहले।)

  • स्टेटिक स्ट्रिंग्स : NSString *foo = @"bar";- क्या आपको इसे बनाए रखना है या रिलीज करना है? कैसे के बारे में

    -(void)getBar {
        return @"bar";
    }

    ...

    NSString *foo = [self getBar]; // still no need to retain or release
  • द क्रिएशन रूल : यदि आपने इसे बनाया है, तो आप इसके मालिक हैं, और इसे जारी करने की उम्मीद है।

सामान्य तौर पर, जिस तरह से नए कोको प्रोग्रामर गड़बड़ हो जाते हैं, यह समझ में नहीं आता है कि कौन सी दिनचर्या किसी वस्तु को वापस करती है retainCount > 0

यहाँ कोको में मेमोरी प्रबंधन के लिए बहुत सरल नियमों से एक स्निपेट दिया गया है :

प्रतिधारण गणना नियम

  • किसी दिए गए ब्लॉक के भीतर -copy, -alloc और -retain का उपयोग -release और -autocelease के उपयोग के बराबर होना चाहिए।
  • सुविधा निर्माणकर्ताओं (जैसे NSString के stringWithString) का उपयोग करके बनाई गई वस्तुओं को ऑटोरेल्ड माना जाता है।
  • अपने-अपने इंस्टेंवेबल्स को जारी करने के लिए एक -dealloc पद्धति को लागू करें

पहली गोली कहती है: यदि आपने फोन किया alloc(या new fooCopy), तो आपको उस ऑब्जेक्ट पर रिलीज़ को कॉल करने की आवश्यकता है।

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

तीसरा स्व-व्याख्यात्मक होना चाहिए।


"ऑटोरेलिज़: डॉक्स का कहना है कि यह भविष्य में किसी बिंदु पर" एक रिलीज को ट्रिगर करेगा। "WHEN ?!" डॉक्स उस बिंदु पर स्पष्ट हैं: "ऑटोरेलिस का अर्थ है" बाद में रिलीज़ संदेश भेजें "(बाद की कुछ परिभाषा के लिए -" ऑटोरेलिज़ पूल "देखें)।" जब ऑटो रिक्शा पूल स्टैक पर निर्भर करता है, तो ठीक है ...
3

... "सिस्टम MAY वर्तमान घटना चक्र के बाद किसी भी समय ऑब्जेक्ट जारी करता है।" यह सिस्टम को ध्वनि के बजाय कम निर्धारक बनाता है ...
mmalc

... NSString फू = [आत्म getBar]; // अभी भी इसे बनाए रखने या जारी करने की कोई आवश्यकता नहीं है यह गलत है। जो कोई भी getBar को लागू करता है, उसे कार्यान्वयन विवरण नहीं पता होता है, इसलिए यदि उन्हें वर्तमान स्कोप के बाहर इसका उपयोग करना है , तो * को बनाए रखना चाहिए (आमतौर पर एक्सेसर्स के माध्यम से)।
4

"मेमोरी में प्रबंधन के लिए बहुत सरल नियम" लेख कई मामलों में पुराना है - विशेष रूप से "सुविधा निर्माणकर्ताओं (उदाहरण के लिए NSString के stringWithString) का उपयोग करके बनाई गई वस्तुओं को ऑटोरेल्ड माना जाता है।" यह सही नहीं है - यह केवल "प्राप्तकर्ता के स्वामित्व में नहीं है"।
mmalc


0

जैसा कि कई लोगों ने पहले ही उल्लेख किया है, Apple का इंट्रो टू मेमोरी मैनेजमेंट अब तक शुरू करने के लिए सबसे अच्छी जगह है।

एक उपयोगी लिंक जो मैंने अभी तक नहीं देखा है वह है प्रैक्टिकल मेमोरी मैनेजमेंट । यदि आप उनके माध्यम से पढ़ते हैं, तो आप इसे Apple के डॉक्स के बीच में पाएंगे, लेकिन यह सीधे लिंक करने लायक है। यह उदाहरणों और सामान्य गलतियों के साथ स्मृति प्रबंधन नियमों का एक शानदार कार्यकारी सारांश है (मूल रूप से यहां अन्य उत्तर क्या समझाने की कोशिश कर रहे हैं, लेकिन साथ ही साथ नहीं)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.