ऑब्जेक्टिव-सी में ऑटोमैटिक रेफरेंस काउंटिंग किस तरह के लीक्स को रोकती या कम नहीं करती?


235

मैक और आईओएस प्लेटफार्मों में, मेमोरी लीक अक्सर अप्रबंधित पॉइंटर्स के कारण होता है। परंपरागत रूप से, यह हमेशा महत्वपूर्ण है कि आपके एलोक, कॉपियों और रिटर्न्स की जाँच करें और सुनिश्चित करें कि प्रत्येक के पास एक जारी संदेश है।

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

लेकिन अन्य मेमोरी लीक क्या करती है नहीं रोकता है कि मुझे अभी भी बाहर देखना है?

एक बोनस के रूप में, मैक ओएस एक्स और आईओएस पर एआरसी और मैक ओएस एक्स पर कचरा संग्रह के बीच अंतर क्या हैं?

जवाबों:


262

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

यह इस कारण से है कि __unsafe_unretainedऔर __weakस्वामित्व वाले क्वालिफायर मौजूद हैं। पूर्व किसी भी वस्तु को इंगित नहीं करेगा जिसे वह इंगित करता है, लेकिन उस वस्तु के दूर जाने की संभावना को छोड़ देता है और यह खराब स्मृति की ओर इशारा करता है, जबकि बाद वाला वस्तु को बनाए नहीं रखता है और अपने लक्ष्य के समाप्त होने पर स्वतः ही शून्य पर सेट हो जाता है। दो में से, __weakआमतौर पर उन प्लेटफार्मों पर पसंद किया जाता है जो इसका समर्थन करते हैं।

आप डेलिगेट जैसी चीजों के लिए इन क्वालीफायर का उपयोग करेंगे, जहाँ आप नहीं चाहते कि ऑब्जेक्ट उसके डेलिगेट को बनाए रखे और संभावित रूप से एक चक्र तक ले जाए।

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

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

बहुत से नए व्यवहार, वस्तुओं को तब तक रखने के आधार पर जब तक कि उनके लिए एक मजबूत सूचक नहीं होता है, मैक पर कचरा संग्रह के समान है। हालाँकि, तकनीकी कमियां बहुत अलग हैं। कचरा उठाने की प्रक्रिया होने के बजाय, जो नियमित अंतराल पर चलती है ताकि वस्तुओं को साफ न किया जा सके, स्मृति प्रबंधन की यह शैली कठोर अनुरक्षण / रिलीज नियमों पर निर्भर करती है, जिन्हें हम सभी को उद्देश्य-सी में पालन करने की आवश्यकता है।

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

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


2
विस्तार से उत्तर के लिए धन्यवाद। मेरे पास एक ही मुद्दा था जहां मैंने _unsafe_unretain के तहत एक प्रतिनिधि को परिभाषित किया और मेरा आवेदन दुर्घटनाग्रस्त हो गया, बाद में इसे मजबूत में बदलकर इसे ठीक कर दिया, लेकिन अब इसकी मेमोरी लीक हो गई है। इसलिए, मैंने इसे कमजोर करने के लिए बदल दिया और आकर्षण की तरह काम करता है।
चतुर्थी

@ichathura वाह! आपने मुझे ARC की मायर से बचाया। CMPopTipView का उपयोग करते समय मैंने उसी क्रैश का सामना किया है।
नियेलियनग

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

ब्रैड, क्रिस लैटनर की कड़ी मर चुकी है । मैं 100% नहीं हूं, लेकिन मुझे यह अन्य लिंक मिला। जो मुझे लगता है कि आप क्या लिंक करना चाहते थे: lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160208/…
Honey

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

14

एआरसी आपको गैर-ओबीजीसी मेमोरी के साथ मदद नहीं करेगा, उदाहरण के लिए यदि आप malloc()कुछ करते हैं, तो आपको अभी भी ज़रूरत हैfree()

एआरसी द्वारा मूर्ख बनाया जा सकता है performSelector: यदि कंपाइलर यह पता नहीं लगा सकता है कि चयनकर्ता क्या है (कंपाइलर उस पर चेतावनी उत्पन्न करेगा)।

ARC ObjC नामकरण सम्मेलनों के बाद कोड भी उत्पन्न करेगा, इसलिए यदि आप ARC और MRC कोड को मिलाते हैं, तो MRC कोड क्या करता है जो कंपाइलर नाम के वादे के बारे में नहीं सोचता है तो आपको आश्चर्यजनक परिणाम मिल सकते हैं।


7

मैंने निम्नलिखित 4 मुद्दों के कारण अपने आवेदन में मेमोरी लीक का अनुभव किया:

  1. व्यू कंट्रोलर्स को खारिज करते समय NSTimers को अमान्य नहीं करना
  2. व्यू कंट्रोलर को खारिज करते हुए NSNotificationCenter में किसी भी पर्यवेक्षक को हटाने के लिए भूल जाना।
  3. ब्लॉकों में स्वयं के लिए मजबूत संदर्भ रखते हुए।
  4. नियंत्रक गुणों को देखते हुए प्रतिनिधियों के लिए मजबूत संदर्भों का उपयोग करना

सौभाग्य से मैं निम्नलिखित ब्लॉग पोस्ट पर आया और उन्हें सही करने में सक्षम था: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four-likely-culprits/


0

ARC भी CoreFoundation प्रकारों का प्रबंधन नहीं करेगा। आप उन्हें (उपयोग करके CFBridgingRelease()) 'पुल' कर सकते हैं, लेकिन केवल तब जब आप इसे ऑब्जेक्टिव-सी / कोको ऑब्जेक्ट के रूप में उपयोग करने जा रहे हों। ध्यान दें कि CFBridgingRelease बस CoreFoundation को 1 से गिनती बनाए रखता है और इसे Objective-C के ARC में ले जाता है।


0

Xcode 9 उस तरह के मुद्दों को खोजने के लिए एक महान उपकरण प्रदान करता है। इसे कहा जाता है: " डिबग मेमोरी ग्राफ़ "। इसका उपयोग करके आप अपनी लीक हुई वस्तु को वर्ग प्रकार से पा सकते हैं और आप स्पष्ट रूप से देख सकते हैं कि कौन इसका मजबूत संदर्भ रखता है, इसे वहां से जारी करके आपकी समस्या हल करता है। यह मेमोरी साइकिल का भी पता लगाता है।

इसका उपयोग कैसे करें के बारे में अधिक जानकारी देखें

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