कब -retainCount का उपयोग करें?


110

मैं जानना चाहूंगा कि आपने -retainCountअब तक किस स्थिति का उपयोग किया है , और अंततः समस्याएं जो इसका उपयोग कर सकती हैं।

धन्यवाद।


5
आपको कभी भी उपयोगकर्ता नहीं करना चाहिए -retainCount
holex

3
(जब आपको चाहिए तब को छोड़कर। यह समझने में मदद करने के लिए कभी-कभी उपयोगी होता है कि क्या हो रहा है, इसलिए जब तक आप सराहना करते हैं कि यह कई बार गंभीर रूप से भ्रामक हो सकता है। और निश्चित रूप से, एआरसी का उपयोग करने पर यह बिल्कुल भी अनुमति नहीं है।)
Hot Licks

जवाबों:


243

आपको कभी भी उपयोग नहीं करना चाहिए -retainCount, क्योंकि यह आपको कभी भी उपयोगी नहीं बताता है। फाउंडेशन और AppKit / UIKit फ्रेमवर्क का कार्यान्वयन अपारदर्शी है; आपको पता नहीं है कि क्या बनाए रखा जा रहा है, क्यों इसे बनाए रखा जा रहा है, कौन इसे बनाए रख रहा है, जब इसे बनाए रखा गया था, और इसी तरह।

उदाहरण के लिए:

  • आपको लगता है कि 1 का [NSNumber numberWithInt:1]होगा retainCount। यह नहीं है। यह 2 है।
  • आपको लगता है कि 1 का @"Foo"होगा retainCount। यह नहीं है। यह 1152921504606846975 है।
  • आपको लगता है कि 1 का [NSString stringWithString:@"Foo"]होगा retainCount। यह नहीं है। दोबारा, यह 1152921504606846975 है।

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

यदि आप नीचे ट्रैक करने की कोशिश कर रहे हैं कि किसी वस्तु को क्यों नहीं हटाया जा रहा है, तो उपकरण में लीक्स टूल का उपयोग करें। यदि आप नीचे ट्रैक करने की कोशिश कर रहे हैं कि किसी वस्तु को बहुत जल्द क्यों डील किया गया था, तो इंस्ट्रूमेंट्स में लाश टूल का उपयोग करें।

लेकिन उपयोग नहीं करते -retainCount। यह वास्तव में एक बेकार विधि है।

संपादित करें

कृपया सभी लोग http://bugreport.apple.com पर जाएँ और अनुरोध करें कि -retainCountपदावनत किया जाए। जितने ज्यादा लोग इसके लिए कहेंगे, उतना अच्छा है।

# 2 संपादित करें

अद्यतन के रूप में, [NSNumber numberWithInt:1]अब retainCount922337203685474780807 में से एक है । यदि आपका कोड 2 होने की उम्मीद कर रहा था, तो आपका कोड अब टूट गया है।


4
आपके उदाहरणों के लिए धन्यवाद @ डेव-डेलॉन्ग।
मोसजी ११'११

1
रिटेनकाउंट वर्तमान में एकल के लिए उपयोगी है। (अब सवाल यह है कि एकल कैसे उपयोगी हैं ...) - (NSUInteger)retainCount{return NSUIntegerMax;}
जो

8
@ जो आप बिना ओवरराइड किए एक सिंगलटन बना सकते हैं retainCount
डेव डेलॉन्ग

5
@ जो मैं इससे अवगत हूँ; Google "उद्देश्य-सी सिंगलटन" इस बात पर सभी चर्चा के लिए कि उदाहरण बहुत अच्छा क्यों नहीं है।
डेव डेलॉन्ग

2
एक चीज जो मैं उपयोग करता हूं - @ डेवडॉन्ग, आपको यह गलत भी लग सकता है, लेकिन मुझे ऐसा नहीं लगता है - डीललॉक्स और इनिट्स को ओवरराइट करना और उनमें NSLogs डालना (यहां तक ​​कि ARC के साथ भी)। यह मुझे एक महान विचार देता है कि क्या वस्तुओं को निपटाया जा रहा है या नहीं, जो कि असली सवाल है जिसका हम आम तौर पर जवाब देने की कोशिश कर रहे हैं ..
Dan Rosenstark

50

कभी नहीँ!

गंभीरता से। बस यह मत करो।

बस मेमोरी मैनेजमेंट दिशानिर्देशों का पालन करें और केवल वही जारी करें जो आप alloc, newया copy(या जो कुछ भी आप retainमूल रूप से कहते हैं )।

@bbum ने SO पर यहाँ सबसे अच्छा कहा , और अपने ब्लॉग पर और भी अधिक विस्तार से ।


8
क्योंकि आपको लगता है कि आप स्मृति की गिनती कर रहे हैं, लेकिन आप इसे गलत कर रहे होंगे।
अबिज़र्न Ab

@Abizern - और अन्य उत्तरों में से एक में सिंगलटन स्थिति के बारे में क्या?
मोसजी

3
इसे जोड़ने के लिए, आपके द्वारा प्राप्त की -retainCountजा सकने वाली कोई भी जानकारी इंस्ट्रूमेंट्स और उसके टूल्स से प्राप्त की जा सकती है।
डेव डोंगलांग

3
डेव ने जो कहा, उसे जोड़ने के लिए; किसी वस्तु की निरपेक्ष अनुवर्ती गणना एक कार्यान्वयन विवरण है। वस्तु के आंतरिक भाग का विस्तार और / या किसी अन्य वस्तु के विस्तार से दोनों को पार किया जा सकता है। कॉलिंग retain, retain, retain, autorelease, autorelease, autoreleaseUIKit एपीआई के माध्यम से एक वस्तु गुजर, उदाहरण के लिए की एक पूरी तरह से वैध परिणाम हो सकता है।
बीबम

2
@ d11wtq अगर कभी भी बरकरार रहे तो == 0, विलक्षणता हासिल कर ली गई है!
bbum

14

ऑटोरेल्ड ऑब्जेक्ट्स एक ऐसा मामला है, जहाँ चेकिंग -retainCount एकरूप और संभावित भ्रामक है। रिटेन काउंट आपको इस बारे में कुछ नहीं बताता है कि किसी ऑब्जेक्ट पर कितनी बार -ऑटोरेलिज को बुलाया गया है और इसलिए वर्तमान ऑटोरेलिज पूल नालियों के चलते कितनी बार इसे छोड़ा जाएगा।


1
धन्यवाद - यह एक अच्छा बिंदु है। यह पहला उत्तर है जो वास्तव में एक कारण है जिसका वर्णन है कि जेनेरिक "नहीं" के अलावा रिटेनकाउंट का उपयोग क्यों न करें।
मोसजी

1
@Moszi: आपका सवाल था "रिटेन का उपयोग कब करें?" - अगर आपको वह सवाल पूछने का मतलब नहीं था, तो आपको कुछ और पूछना चाहिए था।
चक

@chuck - वास्तव में मुझे "जब इसका उपयोग करना था" में दिलचस्पी थी, हालांकि ऐसा लगता है कि हर उत्तर "कभी नहीं" होने वाला है ... लेकिन - मुझे लगता है कि आप सही हैं। मैं कुछ दिनों के लिए प्रश्न को खुला छोड़ दूंगा, और यदि कोई उत्तर नहीं होगा, तो कभी नहीं, तो मैं उत्तर के रूप में "कभी नहीं" स्वीकार करूंगा।
मोसजी

10

जब 'इंस्ट्रूमेंट्स' का उपयोग करके जाँच की जाती है, तो मुझे रिटेंक्शंस बहुत उपयोगी लगते हैं

'आवंटन' टूल का उपयोग करके, सुनिश्चित करें कि 'रिकॉर्ड संदर्भ मायने रखता है' चालू है और आप किसी भी ऑब्जेक्ट में जा सकते हैं और इसका रिटेनटाउन इतिहास देख सकते हैं।

Allocs और रिलीज़ को जोड़कर आप क्या हो रहा है की एक अच्छी तस्वीर प्राप्त कर सकते हैं और अक्सर उन मुश्किल मामलों को हल कर सकते हैं जहां कुछ जारी नहीं किया जा रहा है।

इसने मुझे कभी निराश नहीं किया - जिसमें iOS के शुरुआती बीटा रिलीज़ में बग ढूंढना भी शामिल है।


5

NSObject पर Apple प्रलेखन पर एक नज़र डालें, यह आपके प्रश्न को बहुत कवर करता है: NSObject रिटेनकाउंट

संक्षेप में, जब तक आप अपनी खुद की संदर्भ गणना प्रणाली लागू नहीं करते (और मैं लगभग गारंटी नहीं दे सकता) जब तक कि आप को बनाए रखना संभवत: आपके लिए बेकार है।

Apple के अपने शब्दों में, अनुरक्षण "आम तौर पर स्मृति प्रबंधन मुद्दों को डीबग करने में कोई मूल्य नहीं है"।


सबसे पहले आपको जवाब देने के लिए धन्यवाद। आमतौर पर इस सवाल पर लोगों की प्रतिक्रिया "कभी नहीं" होती है। (उत्तर देखें)। वास्तव में "डिबगिंग में कोई मूल्य नहीं" का अर्थ "कभी नहीं" है। तो मेरा प्रश्न है - इसका उपयोग न करने की प्रबल भावना (उदाहरण के लिए सिंगलटन कार्यान्वयन में - फिर से उत्तरों में से एक) क्यों है?
मोसजी

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

1
@Moszi: डिबगिंग एकमात्र ऐसी स्थिति है जिसमें अधिकांश लोग इसके मूल्य के बारे में गर्भधारण कर सकते हैं, इसलिए यदि यह वहां अविश्वसनीय है, तो यह कभी उपयोगी नहीं है। आप अन्य किन उपयोगों के बारे में सोच रहे हैं?
चक

4

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

अपनी बात को गंभीरता से बताने के प्रयास में आपने मूल्य के असंवेदनशील स्वरूप को गंभीरता से लिया है। यह सच है कि यह हमेशा एक संदर्भ गणना नहीं है। कुछ विशेष मूल्य हैं जो झंडे के लिए उपयोग किए जाते हैं, उदाहरण के लिए यह इंगित करने के लिए कि किसी वस्तु को कभी नहीं हटाया जाना चाहिए। 1152921504606846975 जैसी संख्या बहुत ही रहस्यमय लगती है जब तक कि आप इसे हेक्स में लिखते हैं और 0xfffffffffffff प्राप्त करते हैं। और 922337203685474780807 हेक्स में 0x7fffffffffffffff है। और यह वास्तव में इतना आश्चर्य की बात नहीं है कि कोई व्यक्ति झंडे के रूप में इन जैसे मूल्यों का उपयोग करना पसंद करेगा, यह देखते हुए कि रिटेनकाउंट पाने के लिए लगभग 3000 साल लगेंगे जितनी बड़ी संख्या, आप प्रति सेकंड 100,000,000 बार रिटेनकाउंट बढ़ाएंगे।


3

इसका उपयोग करने से आपको क्या समस्याएं हो सकती हैं? यह सब कुछ ऑब्जेक्ट की रिटेन काउंट लौटाता है। मैंने इसे कभी नहीं बुलाया और किसी भी कारण से नहीं सोच सकता कि मैं करूंगा। मैंने यह सुनिश्चित करने के लिए इसे एकल में ओवरराइड कर दिया है, हालांकि यह सुनिश्चित नहीं किया गया है कि वे समाप्त नहीं हुए हैं।


2
सिंगलटन मामले में इसे ओवरराइड करने का कोई कारण नहीं है। फाउंडेशन / CoreFoundation में कोई कोड पथ नहीं हैं जो retainCountमेमोरी प्रबंधन के लिए उपयोग करते हैं।
बीबीम

क्या यह निश्‍चित करने के लिए उपयोग नहीं करता है कि क्या इसे डीललॉक कहा जाना चाहिए?
उघौवगफह्व

2
नहीं; अनुरक्षण / रिलीज / ऑटोरेलिज के आंतरिक कार्यान्वयन की कोरफ़ाउंडेशन में गहरी जड़ें हैं और वास्तव में वह बिल्कुल नहीं है जो आप उम्मीद कर सकते हैं। CoreFoundation source को पकड़ो (यह उपलब्ध है) और देखो।
बबम

3

जब तक आपका ऐप उठ रहा है और चल रहा है और कुछ उपयोगी काम कर रहा है, तब तक आपको मेमोरी लीक होने की चिंता नहीं होनी चाहिए।

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

अपने कोड को आज़माएं और अनुकूलित न करें क्योंकि आप इसे लिख रहे हैं, आपके अनुमानों के अनुसार मेमोरी लीक हो सकती है या बहुत अधिक समय लग सकता है जब आप वास्तव में सामान्य रूप से ऐप का उपयोग करते हैं तो अक्सर गलत होते हैं।

कोशिश करें और सही कोड लिखें जैसे यदि आप आवंटित और इस तरह का उपयोग करके कोई ऑब्जेक्ट बनाते हैं, तो सुनिश्चित करें कि आप इसे ठीक से जारी करते हैं।


0

आपको इसे अपने कोड में कभी भी उपयोग नहीं करना चाहिए, लेकिन डिबगिंग के समय यह निश्चित रूप से मदद कर सकता है


0

अपने कोड में कभी -retainCount का उपयोग न करें। हालाँकि यदि आप उपयोग करते हैं, तो आप कभी भी इसे शून्य नहीं देखेंगे। क्यों सोचें। :-)


0

डेव के पोस्ट में उपयोग किए गए उदाहरण NSNumber और NSStrings हैं ... इसलिए, यदि आप कुछ अन्य वर्गों का उपयोग करते हैं, जैसे कि UIViews, तो मुझे यकीन है कि आपको सही उत्तर मिलेगा (रिटेन काउंट कार्यान्वयन पर निर्भर करता है, और यह अनुमानित है)।

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