फिजिकल लीक्स
जिस तरह के बग जीसी पते लगते हैं (कम से कम बाहरी पर्यवेक्षक के लिए) उस तरह की चीजें जो एक प्रोग्रामर को अच्छी तरह से पता है कि उसकी भाषा, पुस्तकालय, अवधारणाएं, मुहावरे आदि नहीं करेंगे। लेकिन मैं गलत हो सकता है: मैन्युअल मेमोरी हैंडलिंग आंतरिक रूप से जटिल है?
सी एंड से आ रहा है, जो मेमोरी प्रबंधन को मैनुअल के रूप में बनाता है और जितना संभव हो उतना उच्चारित किया जाता है ताकि हम चरम सीमाओं (सी ++ ज्यादातर जीसी के बिना मेमोरी प्रबंधन को स्वचालित कर सकें), मैं जीसी से तुलना करने के अर्थ में "वास्तव में नहीं" कहूंगा। लीक पर आता है । एक शुरुआत और कभी-कभी एक समर्थक भी free
दिए गए के लिए लिखना भूल सकता है malloc
। यह निश्चित रूप से होता है।
हालांकि, valgrind
रिसाव का पता लगाने जैसे उपकरण हैं जो कोड को निष्पादित करने पर तुरंत हाजिर हो जाएंगे, जब / जहां ऐसी गलतियां कोड की सटीक रेखा तक होती हैं। जब इसे सीआई में एकीकृत किया जाता है, तो ऐसी गलतियों को मर्ज करना लगभग असंभव हो जाता है, और उन्हें सही करने के लिए पाई के रूप में आसान है। इसलिए यह उचित मानकों के साथ किसी भी टीम / प्रक्रिया में एक बड़ी बात नहीं है।
दी गई है, निष्पादन के कुछ विदेशी मामले हो सकते हैं जो परीक्षण के रडार के तहत उड़ान भरते हैं जहां free
बुलाया जाना विफल होता है, शायद एक भ्रष्ट फ़ाइल जैसी अस्पष्ट बाहरी इनपुट त्रुटि का सामना करने पर जिसमें सिस्टम शायद 32 बाइट्स या कुछ लीक करता है। मुझे लगता है कि निश्चित रूप से बहुत अच्छे परीक्षण मानकों और रिसाव का पता लगाने वाले उपकरणों के तहत भी हो सकता है, लेकिन यह भी इतना महत्वपूर्ण नहीं होगा कि किसी चीज़ पर थोड़ी सी भी स्मृति को लीक कर दिया जाए जो लगभग कभी नहीं होता है। हम एक बहुत बड़ा मुद्दा देखेंगे जहां हम बड़े पैमाने पर संसाधनों को सामान्य निष्पादन पथों में भी लीक कर सकते हैं जो जीसी को रोक नहीं सकते हैं।
जब जीसी के छद्म रूप (संदर्भ गिनती, उदाहरण) जैसे कुछ के बिना यह भी मुश्किल होता है, जब किसी वस्तु के जीवनकाल को किसी अन्य प्रकार के आस्थगित / अतुल्यकालिक प्रसंस्करण के लिए विस्तारित करने की आवश्यकता होती है, शायद।
दंगल पॉइंट्स
स्मृति प्रबंधन के अधिक मैनुअल रूपों के साथ वास्तविक मुद्दा मेरे लिए लीक नहीं है। C या C ++ में लिखे गए कितने मूल एप्लिकेशन हैं जो हमें पता है कि वास्तव में लीक हैं? क्या लिनक्स कर्नेल लीक है? माई एसक्यूएल? क्रायंगाइन 3? डिजिटल ऑडियो वर्कस्टेशन और सिंथेसाइज़र? क्या जावा वीएम लीक (यह देशी कोड में लागू किया गया है)? फोटोशॉप?
अगर कुछ भी, मुझे लगता है कि जब हम चारों ओर देखते हैं, तो लीकेज एप्लिकेशन जीसी योजनाओं का उपयोग करके लिखे गए होते हैं। लेकिन इससे पहले कि कचरा संग्रह पर एक स्लैम के रूप में लिया जाता है, देशी कोड में एक महत्वपूर्ण मुद्दा है जो मेमोरी लीक से बिल्कुल भी संबंधित नहीं है।
मेरे लिए मुद्दा हमेशा सुरक्षा का था। यहां तक कि जब हम free
एक पॉइंटर के माध्यम से मेमोरी करते हैं , तो यदि संसाधन में कोई अन्य पॉइंटर्स हैं, तो वे झूलने (अमान्य) पॉइंटर्स बन जाएंगे।
जब हम उन झूलने वाले बिंदुओं के पॉइट्स तक पहुंचने का प्रयास करते हैं, तो हम अनिर्धारित व्यवहार में भाग लेते हैं, हालांकि लगभग हमेशा एक सेगफॉल्ट / एक्सेस उल्लंघन एक कठिन, तत्काल दुर्घटना का कारण बनता है।
संभावित रूप से ऊपर सूचीबद्ध उन सभी मूल अनुप्रयोगों में एक अस्पष्ट किनारे का मामला है या दो जो मुख्य रूप से इस मुद्दे के कारण दुर्घटना का कारण बन सकते हैं, और निश्चित रूप से देशी कोड में लिखे गए घटिया अनुप्रयोगों का एक उचित हिस्सा है जो बहुत दुर्घटना-भारी हैं, और अक्सर इस मुद्दे के कारण बड़े हिस्से में।
... और ऐसा इसलिए है क्योंकि आप जीसी का उपयोग करते हैं या नहीं, इसकी परवाह किए बिना संसाधन प्रबंधन कठिन है। व्यावहारिक अंतर अक्सर या तो लीक हो रहा है (जीसी) या क्रैश (जीसी के बिना) एक गलती के कारण संसाधन कुप्रबंधन के कारण।
संसाधन प्रबंधन: कचरा संग्रह
जटिल संसाधन प्रबंधन एक कठिन, मैन्युअल प्रक्रिया है, चाहे जो भी हो। जीसी यहां कुछ भी स्वचालित नहीं कर सकता है।
चलो एक उदाहरण लेते हैं जहां हमारे पास यह वस्तु है, "जो"। जो को कई संगठनों द्वारा संदर्भित किया जाता है, जिसमें वह एक सदस्य है। हर महीने या तो वे अपने क्रेडिट कार्ड से सदस्यता शुल्क निकालते हैं।
हमारे पास अपने जीवनकाल को नियंत्रित करने के लिए जो के लिए एक संदर्भ भी है। मान लीजिए, प्रोग्रामर के रूप में, हमें अब जो की जरूरत नहीं है। वह हमें परेशान करना शुरू कर रहा है और हमें अब इन संगठनों की आवश्यकता नहीं है जो उसके साथ अपना समय बर्बाद करने से संबंधित हैं। इसलिए हम उसके जीवन रेखा के संदर्भ को हटाकर उसे पृथ्वी के सामने से मिटाने का प्रयास करते हैं।
... लेकिन रुकिए, हम कचरा संग्रहण का उपयोग कर रहे हैं। जो के लिए हर मजबूत संदर्भ उसे चारों ओर रखेगा। इसलिए हम उनसे उन संगठनों के संदर्भ भी हटा देते हैं, जिनसे वह संबंध रखते हैं (उन्हें अनसब्सक्राइब करते हुए)।
... व्हाट्सएप को छोड़कर, हम उनकी पत्रिका सदस्यता रद्द करना भूल गए! अब जो स्मृति में रहता है, हमें परेशान करता है और संसाधनों का उपयोग करता है, और पत्रिका कंपनी हर महीने जोए की सदस्यता की प्रक्रिया को जारी रखती है।
यह मुख्य गलती है जो कचरा संग्रह योजनाओं के उपयोग से लिखे गए बहुत सारे जटिल कार्यक्रमों को लीक करने और अधिक से अधिक मेमोरी का उपयोग करना शुरू कर सकती है जो वे लंबे समय तक चलाते हैं, और संभवतः अधिक से अधिक प्रसंस्करण (आवर्ती पत्रिका सदस्यता)। वे उन संदर्भों में से एक या एक से अधिक को निकालना भूल गए, जिससे कचरा कलेक्टर के लिए अपना जादू करना असंभव हो गया जब तक कि पूरे कार्यक्रम को बंद नहीं किया गया।
हालांकि, कार्यक्रम दुर्घटना नहीं करता है। यह पूरी तरह से सुरक्षित है। यह सिर्फ याददाश्त को बनाए रखने वाला है और जो अब भी इधर-उधर घूमता रहेगा। कई अनुप्रयोगों के लिए, इस प्रकार का टपका हुआ व्यवहार जहां हम सिर्फ अधिक से अधिक स्मृति / प्रसंस्करण को समस्या में फेंक देते हैं, शायद ही एक कठिन दुर्घटना के लिए बेहतर हो सकता है, विशेष रूप से यह देखते हुए कि हमारी मशीनों में कितनी स्मृति और प्रसंस्करण शक्ति है।
संसाधन प्रबंधन: मैनुअल
अब आइए उस विकल्प पर विचार करें जहां हम जो और मैनुअल मेमोरी मैनेजमेंट जैसे पॉइंटर्स का उपयोग करते हैं, जैसे:
ये नीले लिंक जो के जीवनकाल का प्रबंधन नहीं करते हैं। यदि हम उसे पृथ्वी के सामने से हटाना चाहते हैं, तो हम स्वयं उसे नष्ट करने का अनुरोध करते हैं, जैसे:
अब जो सामान्य रूप से हमें सभी स्थानों पर झूलने वाले बिंदुओं के साथ छोड़ देगा, तो चलो जो को इंगित करने वाले बिंदुओं को हटा दें।
... वूप्स, हमने फिर से वही गलती की और जो की पत्रिका सदस्यता को सदस्यता समाप्त करना भूल गए!
सिवाय अब हमारे पास एक लटकता हुआ सूचक है। जब पत्रिका सदस्यता जो के मासिक शुल्क को संसाधित करने की कोशिश करती है, तो पूरी दुनिया में विस्फोट हो जाएगा - आमतौर पर हमें तुरंत दुर्घटना होती है।
यह वही बुनियादी संसाधन कुप्रबंधन गलती है जहाँ डेवलपर मैन्युअल रूप से सभी बिंदुओं / संदर्भों को हटाना भूल जाता है, जिससे मूल अनुप्रयोगों में बहुत सारे क्रैश हो सकते हैं। वे स्मृति को अधिक देर तक नहीं चलाते हैं क्योंकि वे आमतौर पर चलते हैं क्योंकि वे अक्सर इस मामले में एकमुश्त दुर्घटना करेंगे।
असली दुनिया
अब उपरोक्त उदाहरण एक हास्यास्पद सरल आरेख का उपयोग कर रहा है। एक वास्तविक दुनिया के अनुप्रयोग को एक पूर्ण ग्राफ़ को कवर करने के लिए एक साथ सिले हजारों छवियों की आवश्यकता हो सकती है, जिसमें सैकड़ों विभिन्न प्रकार के संसाधनों को एक दृश्य ग्राफ में संग्रहीत किया जाता है, उनमें से कुछ से जुड़े GPU संसाधन, दूसरों से बंधे त्वरक, सैकड़ों प्लगइन्स में पर्यवेक्षक वितरित किए जाते हैं परिवर्तनों के लिए दृश्य में कई प्रकार की संस्थाएं देख रहे हैं, पर्यवेक्षक, पर्यवेक्षकों का अवलोकन, एनिमेशन के लिए समन्वयित ऑडिएंस इत्यादि, इसलिए ऐसा लग सकता है कि मैंने ऊपर वर्णित गलती से बचना आसान है, लेकिन यह आम तौर पर एक वास्तविक दुनिया में इस सरल के पास कहीं नहीं है। कोड के लाखों लाइनों के एक जटिल अनुप्रयोग के लिए उत्पादन कोडबेस।
मौका है कि किसी को, किसी दिन, संसाधनों को गलत तरीके से उस कोडबेस में कहीं अधिक हो जाएगा, और संभावना जीसी के साथ या उसके बिना एक ही है। मुख्य अंतर यह है कि इस गलती के परिणामस्वरूप क्या होगा, जो संभावित रूप से यह भी प्रभावित करता है कि यह गलती कितनी जल्दी स्पॉट और तय हो जाएगी।
क्रैश बनाम लीक
अब कौन सा बदतर है? एक तत्काल दुर्घटना, या एक खामोश स्मृति रिसाव जहां जो बस रहस्यमय तरीके से आसपास रहती है?
अधिकांश उत्तरार्द्ध का उत्तर दे सकते हैं, लेकिन मान लें कि इस सॉफ़्टवेयर को अंत में, संभवतः दिनों पर चलाने के लिए डिज़ाइन किया गया है, और इनमें से प्रत्येक जो और जेन के हम जोड़ते हैं, एक गीगाबाइट द्वारा सॉफ़्टवेयर के मेमोरी उपयोग को बढ़ाता है। यह एक मिशन-महत्वपूर्ण सॉफ़्टवेयर नहीं है (क्रैश वास्तव में उपयोगकर्ताओं को नहीं मारता है), लेकिन एक प्रदर्शन-महत्वपूर्ण।
इस मामले में, एक कठिन दुर्घटना जो डिबगिंग करते समय तुरंत दिखाई देती है, जो आपके द्वारा की गई गलती को इंगित करती है, वास्तव में सिर्फ एक लीक सॉफ्टवेयर के लिए बेहतर हो सकता है जो आपके परीक्षण प्रक्रिया के रडार के नीचे भी उड़ सकता है।
दूसरी तरफ, यदि यह एक मिशन-क्रिटिकल सॉफ्टवेयर है, जहां प्रदर्शन लक्ष्य नहीं है, बस किसी भी तरह से दुर्घटनाग्रस्त नहीं हो सकता है, तो लीक करना वास्तव में बेहतर हो सकता है।
कमजोर संदर्भ
कमजोर संदर्भ के रूप में जानी जाने वाली जीसी योजनाओं में इन विचारों का एक प्रकार उपलब्ध है। कमजोर संदर्भों के साथ, हमारे पास ये सभी संगठन कमजोर-संदर्भ जो हो सकते हैं, लेकिन मजबूत संदर्भ (जो के मालिक / जीवन रेखा) के चले जाने पर उसे हटाए जाने से नहीं रोक सकते। फिर भी, हमें यह पता लगाने में सक्षम होने का लाभ मिलता है कि जो अब इन कमजोर संदर्भों के आसपास नहीं है, जिससे हमें आसानी से पुन: प्राप्त होने की अनुमति मिलती है।
दुर्भाग्य से कमजोर संदर्भों का उपयोग लगभग उतना नहीं किया जाता है जितना संभवत: उनका उपयोग किया जाना चाहिए, इसलिए अक्सर बहुत सारे जटिल जीसी अनुप्रयोगों को लीक होने की संभावना हो सकती है, भले ही वे एक जटिल सी अनुप्रयोग की तुलना में संभवतः बहुत कम दुर्घटनाग्रस्त हों, जैसे।
किसी भी मामले में, जीसी आपके जीवन को आसान या कठिन बनाता है या नहीं, यह इस बात पर निर्भर करता है कि लीक से बचने के लिए आपके सॉफ्टवेयर के लिए यह कितना महत्वपूर्ण है, और इस तरह के जटिल संसाधन प्रबंधन से संबंधित है या नहीं।
मेरे मामले में, मैं एक प्रदर्शन-महत्वपूर्ण क्षेत्र में काम करता हूं जहां संसाधन सैकड़ों मेगाबाइट से गीगाबाइट तक फैलाते हैं, और उस मेमोरी को जारी नहीं करते हैं जब उपयोगकर्ता ऊपर की तरह एक गलती के कारण अनलोड करने का अनुरोध करते हैं, वास्तव में किसी दुर्घटना के लिए कम बेहतर हो सकता है । क्रैश स्पॉट करना और पुन: उत्पन्न करना आसान है, जिससे वे अक्सर प्रोग्रामर की पसंदीदा प्रकार की बग बनाते हैं, भले ही यह उपयोगकर्ता का सबसे कम पसंदीदा हो, और इनमें से बहुत सारे क्रैश उपयोगकर्ता तक पहुँचने से पहले एक परीक्षण परीक्षण प्रक्रिया के साथ दिखाई देंगे।
वैसे भी, जीसी और मैनुअल मेमोरी प्रबंधन के बीच अंतर हैं। आपके तात्कालिक प्रश्न का उत्तर देने के लिए, मैं कहूंगा कि मैनुअल मेमोरी प्रबंधन कठिन है, लेकिन लीक से इसका बहुत कम लेना-देना है, और संसाधन प्रबंधन के गैर-तुच्छ होने पर मेमोरी प्रबंधन के GC और मैन्युअल दोनों रूप अभी भी बहुत कठिन हैं । जीसी का यकीनन यहां बहुत अधिक व्यवहार है जहां कार्यक्रम ठीक काम करता प्रतीत होता है लेकिन अधिक से अधिक संसाधनों का उपभोग कर रहा है। मैनुअल फॉर्म कम मुश्किल है, लेकिन ऊपर दिखाए गए की तरह गलतियों के साथ बड़ा समय दुर्घटनाग्रस्त और जलने वाला है।