मेमोरी-अनवांटेड प्रोग्रामिंग की जटिलताएँ क्या हैं?


24

या दूसरे शब्दों में, स्वचालित कचरा संग्रहण से किन विशिष्ट समस्याओं का समाधान हुआ? मैंने कभी भी निम्न-स्तरीय प्रोग्रामिंग नहीं की है, इसलिए मुझे नहीं पता कि संसाधनों को मुक्त करना कितना जटिल हो सकता है।

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


3
कृपया यह बताने के लिए कि आपके सवाल का विकिपीडिया लेख गरबे संग्रह पर और अधिक विशेष रूप से इसके लाभों
yannis

एक अन्य लाभ सुरक्षा है, उदाहरण के लिए बफर ओवररन अत्यधिक शोषक हैं और मेमोरी (मिस) प्रबंधन से कई अन्य सुरक्षा कमजोरियां उत्पन्न होती हैं।
स्टुपरयूजर

7
@StuperUser: जिसका मेमोरी की उत्पत्ति से कोई लेना-देना नहीं है। आप स्मृति को बफर कर सकते हैं जो एक जीसी से आया था बस ठीक है। तथ्य यह है कि जीसी भाषाएं आमतौर पर इसे रोकती हैं, यह ऑर्थोगोनल है, और जीसी तकनीक से तीस साल से कम की भाषाएं जो आप उनकी तुलना कर रहे हैं, बफर बफर सुरक्षा की पेशकश भी कर रहे हैं।
11:16 बजे डेडएमजी

जवाबों:


29

मैंने कभी भी निम्न-स्तरीय प्रोग्रामिंग नहीं की है, इसलिए मुझे नहीं पता कि संसाधनों को मुक्त करना कितना जटिल हो सकता है।

मजेदार है कि कैसे "निम्न-स्तर" की परिभाषा समय के साथ बदलती है। जब मैं पहली बार प्रोग्राम करना सीख रहा था, तो कोई भी भाषा जो एक मानकीकृत हीप मॉडल प्रदान करती थी, जो एक सरल आवंटित / मुक्त पैटर्न संभव बनाता है, वास्तव में उच्च-स्तरीय माना जाता था। में निम्न स्तर के प्रोग्रामिंग , आप स्मृति अपने आप को, पर नज़र रखने होगा (नहीं आवंटन, लेकिन स्मृति स्थल के लिए खुद को!), या अपने स्वयं के ढेर संभाजक बारे में यदि आप वास्तव में कल्पना महसूस कर रहे थे।

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

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

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

सौभाग्य से, इस मुद्दे से निपटना मूल रूप से एक हल की गई समस्या है। आपको कूड़ा उठाने वाले की आवश्यकता नहीं है, आपको डिबगिंग मेमोरी मैनेजर की आवश्यकता है मैं डेल्फी का उपयोग करता हूं, उदाहरण के लिए, और एक एकल बाहरी पुस्तकालय और एक सरल संकलक निर्देश के साथ, मैं "पूर्ण डिबग मोड" के लिए आवंटितकर्ता सेट कर सकता हूं। यह कुछ सुविधाओं को सक्षम करने के बदले में एक नगण्य (5% से कम) प्रदर्शन उपरि जोड़ता है जो कि उपयोग की गई मेमोरी का ट्रैक रखता है। यदि मैं किसी वस्तु को मुक्त करता हूं, तो वह अपनी स्मृति को भर देती है0x80बाइट्स (डिबगर में आसानी से पहचाने जाने योग्य) और अगर मैं कभी किसी फ्रीड ऑब्जेक्ट पर वर्चुअल मेथड (डिस्ट्रॉक्टर सहित) को कॉल करने का प्रयास करता हूं, तो यह तीन स्टैक निशान के साथ एक त्रुटि बॉक्स के साथ प्रोग्राम को नोटिस करता है और बाधित करता है - जब ऑब्जेक्ट बनाया गया था, तो जब इसे मुक्त किया गया था, और मैं अभी कहाँ हूँ - इसके अलावा कुछ अन्य उपयोगी जानकारी, तो एक अपवाद उठाता है। यह स्पष्ट रूप से रिलीज़ बिल्ड के लिए उपयुक्त नहीं है, लेकिन यह ट्रैकिंग को कम करता है और झूलने वाले संदर्भ मुद्दों को ठीक करता है।

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

अगर मैं ऐसा कुछ कहने की कोशिश करता हूं, तो शायद मैं GC के समर्थकों से मिलने जाऊंगा, इसलिए मुझे समझाने की अनुमति दें। याद रखें कि स्मृति रिसाव की परिभाषा आवंटित स्मृति पर है जब आपको इसकी आवश्यकता नहीं होती है। किसी चीज का कोई संदर्भ नहीं होने के अलावा, आप इसके अनावश्यक संदर्भ होने पर भी मेमोरी को लीक कर सकते हैं, जैसे कि कंटेनर ऑब्जेक्ट में इसे पकड़ना जब आपको इसे मुक्त करना चाहिए था। मैंने कुछ मेमोरी लीक्स को ऐसा करने के कारण देखा है, और उन्हें यह ट्रैक करना बहुत मुश्किल है कि आपके पास GC है या नहीं, क्योंकि उनमें मेमोरी के लिए पूरी तरह से वैध संदर्भ शामिल है और डीबगिंग टूल्स के लिए कोई स्पष्ट "बग" नहीं हैं। पकड़। जहां तक ​​मुझे पता है, कोई स्वचालित उपकरण नहीं है जो आपको इस प्रकार की मेमोरी लीक को पकड़ने की अनुमति देता है।

तो एक कचरा संग्रहकर्ता केवल नो-रेफरेंस किस्म के मेमोरी लीक के साथ ही चिंता करता है, क्योंकि यह एकमात्र प्रकार है जिसे एक स्वचालित फैशन से निपटा जा सकता है। यदि यह आपके सभी संदर्भों को सब कुछ देख सकता है और हर वस्तु को मुक्त कर सकता है जैसे ही इसके पास शून्य संदर्भ हैं, तो यह सही होगा, कम से कम नो-रेफरेंस समस्या के संबंध में। इसे स्वचालित तरीके से करने को संदर्भ गिनती कहा जाता है , और इसे कुछ सीमित स्थितियों में किया जा सकता है, लेकिन इससे निपटने के लिए इसके अपने मुद्दे हैं। (उदाहरण के लिए, ऑब्जेक्ट A, ऑब्जेक्ट B के संदर्भ को धारण करता है, जो ऑब्जेक्ट A का संदर्भ रखता है। संदर्भ-गिनती योजना में, न तो ऑब्जेक्ट को स्वचालित रूप से मुक्त किया जा सकता है, तब भी जब A या B में से कोई भी बाहरी संदर्भ न हो) कचरा बीनने वाले ट्रेसिंग का उपयोग करते हैंइसके बजाय: ज्ञात-अच्छी वस्तुओं के एक सेट के साथ शुरू करें, सभी वस्तुओं को देखें जो वे संदर्भ देते हैं, उन सभी वस्तुओं को खोजें जो वे संदर्भ देते हैं, और इसलिए पुनरावृत्ति पर जब तक कि आपने सब कुछ नहीं पाया। ट्रेसिंग प्रक्रिया में जो कुछ भी नहीं मिलता है वह कचरा है और इसे फेंक दिया जा सकता है। (यह सफलतापूर्वक कर रहा है, निश्चित रूप से, एक प्रबंधित भाषा की आवश्यकता होती है जो टाइप सिस्टम पर कुछ प्रतिबंध लगाती है ताकि यह सुनिश्चित हो सके कि ट्रेसिंग कचरा कलेक्टर हमेशा एक संदर्भ और कुछ यादृच्छिक स्मृति के बीच का अंतर बता सकता है जो एक सूचक की तरह दिखता है।)

ट्रेसिंग के साथ दो समस्याएं हैं। सबसे पहले, यह धीमा है, और जब यह हो रहा है तो दौड़ की स्थिति से बचने के लिए कार्यक्रम को कम या ज्यादा रोका जाना चाहिए। यह ध्यान देने योग्य निष्पादन की हिचकी पैदा कर सकता है जब प्रोग्राम को एक उपयोगकर्ता के साथ बातचीत करने वाला माना जाता है, या सर्वर ऐप में bogged-down प्रदर्शन। इसे विभिन्न तकनीकों द्वारा कम किया जा सकता है, जैसे कि आवंटित पीढ़ियों को "पीढ़ियों" में इस सिद्धांत पर तोड़ना कि यदि कोई आवंटन पहली बार आपके द्वारा एकत्र किए गए प्रयास को एकत्र नहीं करता है, तो यह थोड़ी देर के लिए आसपास रहने की संभावना है। .NET फ्रेमवर्क और JVM दोनों जेनरल कचरा संग्राहक का उपयोग करते हैं।

दुर्भाग्य से, यह दूसरी समस्या में शामिल है: जब आप इसके साथ काम करते हैं तो स्मृति मुक्त नहीं हो पाती है। जब तक आप किसी वस्तु के साथ समाप्त होने के तुरंत बाद ट्रेसिंग नहीं चलाते हैं, यह अगली ट्रेस तक, या उससे भी अधिक समय तक इधर-उधर रहेगी, अगर यह इसे पहली पीढ़ी से आगे नहीं बढ़ाती है। वास्तव में, .NET कचरा कलेक्टर के सबसे अच्छे स्पष्टीकरणों में से एक मैंने देखा है जो बताता है कि, इस प्रक्रिया को जितनी जल्दी हो सके, जीसी को उतने लंबे समय तक संग्रह को स्थगित करना पड़ता है! तो मेमोरी लीक्स की समस्या "हल" है बल्कि विचित्र रूप से जितनी देर तक संभव हो उतनी मेमोरी लीक करके ! इसका मतलब है कि जब मैं कहता हूं कि जीसी हर आवंटन को मेमोरी लीक में बदल देता है। वास्तव में, इस बात की कोई गारंटी नहीं है कि किसी भी दी गई वस्तु को कभी भी एकत्र किया जाएगा।

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

दूसरा, अनावश्यक रूप से बड़ी मात्रा में मेमोरी को होल्ड करना, एक आधुनिक मल्टीटास्किंग सिस्टम में समस्याएं पैदा कर सकता है। यदि आप बहुत अधिक भौतिक मेमोरी लेते हैं, तो यह आपके प्रोग्राम या अन्य कार्यक्रमों को पृष्ठ पर लाने का कारण बन सकता है (उनकी मेमोरी में से कुछ को डिस्क पर स्वैप करें) जो वास्तव में चीजों को धीमा कर देता है। कुछ sytems के लिए, जैसे सर्वर, पेजिंग न केवल सिस्टम को धीमा कर सकता है , अगर यह लोड के तहत है तो यह पूरी चीज़ को क्रैश कर सकता है।

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

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

जब आप वास्तव में इसे देखते हैं, तो कूड़े का संग्रह झूलने वाले संदर्भों को रोकने के साथ अच्छा नहीं कर सकता है या नहीं कर सकता है, और सार्वभौमिक रूप से स्मृति लीक से निपटने में एक बुरा काम करता है। इसका एक गुण, वास्तव में, कचरा संग्रह ही नहीं है, बल्कि एक साइड-इफेक्ट है: यह कूल्हे संघनन करने के लिए एक स्वचालित तरीका प्रदान करता है। यह एक आर्कन समस्या (हीप विखंडन के माध्यम से मेमोरी थकावट) को रोक सकता है जो ऐसे प्रोग्राम्स को मार सकता है जो लगातार लंबे समय तक चलते हैं और मेमोरी मंथन की एक उच्च डिग्री होती है, और कचरा संग्रह के बिना हीप संघनन बहुत अधिक असंभव है। हालांकि, इन दिनों कोई भी अच्छा मेमोरी एलोकेटर विखंडन को कम करने के लिए बाल्टी का उपयोग करता है, जिसका अर्थ है कि विखंडन केवल सही मायने में चरम परिस्थितियों में एक समस्या बन जाता है। एक कार्यक्रम जिसमें ढेर विखंडन एक समस्या होने की संभावना है, के लिए ' एक कॉम्पैक्ट कचरा कलेक्टर का उपयोग करने की सलाह दी जाती है। लेकिन किसी अन्य मामले में IMO, कचरा संग्रह का उपयोग समय से पहले अनुकूलन है, और बेहतर समाधान उन समस्याओं के लिए मौजूद हैं जो इसे "स्वीकार करते हैं।"


5
मुझे यह जवाब पसंद है - मैं इसे हर बार पढ़ता रहता हूं। एक प्रासंगिक टिप्पणी के साथ नहीं आ सकता है तो मैं बस इतना कह सकता हूं - धन्यवाद।
वीवी

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

7
@ थोमस एडिंग: जीसी निश्चित रूप से एक अनुकूलन है; यह प्रदर्शन और विभिन्न अन्य कार्यक्रम गुणवत्ता मैट्रिक्स की कीमत पर न्यूनतम प्रोग्रामर प्रयास के लिए अनुकूलन करता है ।
मेसन व्हीलर

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

1
जंग हालांकि, कचरा-संग्रह का उपयोग नहीं करता है, यह संदर्भ-गिनती का उपयोग करता है कि कैसे मेसन का वर्णन है, बस रन-टाइम में त्रुटियों का पता लगाने के लिए डिबगर का उपयोग करने के बजाय व्यापक संकलन-समय की जांच के साथ ...
सीन बर्टन

13

गैर-कचरा-संग्रहित स्मृति प्रबंधन तकनीक को समतुल्य युग से लेकर वर्तमान लोकप्रिय प्रणालियों जैसे कि C ++ के RAII जैसे उपयोग करने वाले कचरा संग्रहकों के रूप में माना जाता है। इस दृष्टिकोण को देखते हुए, तब स्वचालित कचरा संग्रह का उपयोग नहीं करने की लागत न्यूनतम है, और जीसी इसकी बहुत सारी समस्याओं का परिचय देता है। जैसे, मैं सुझाव दूंगा कि "ज्यादा नहीं" आपकी समस्या का जवाब है।

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

कचरा संग्रहकर्ता संदर्भ चक्रों को अधिक आसानी से संभाल सकते हैं, हालांकि ये बहुत दुर्लभ अनुभव हैं। इसके अलावा, जीसीएस सिर्फ "थ्रो अप" कोड कर सकते हैं क्योंकि जीसी सभी मेमोरी प्रबंधन का ध्यान रखेगा, जिसका अर्थ है कि वे तेज देव चक्र को जन्म दे सकते हैं।

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

संपादित करें: आपके द्वारा उल्लिखित कई चीजों का जीसी से कोई लेना-देना नहीं है। आप स्मृति प्रबंधन और ऑब्जेक्ट ओरिएंटेशन को भ्रमित कर रहे हैं। देखिए, यहां बात यह है: यदि आप पूरी तरह से अनवांटेड सिस्टम में प्रोग्राम करते हैं, जैसे कि C ++, तो आपके पास जितना संभव हो, उतनी ही सीमा की जाँच हो सकती है, और मानक कंटेनर कक्षाएं इसे प्रदान करती हैं। उदाहरण के लिए, या मजबूत टाइपिंग की जाँच के बारे में GC कुछ भी नहीं है।

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

संपादित करें: यह ध्यान देने योग्य है कि अधिक उन्नत तकनीकें किसी भी रूप में गतिशील मेमोरी आवंटन की आवश्यकता से बच सकती हैं। उदाहरण के लिए, इस के उपयोग पर विचार करें , जो C ++ में वाई-संयोजन को लागू करता है जिसमें कोई गतिशील आवंटन नहीं है।


यहां विस्तारित चर्चा को साफ किया गया है: अगर हर कोई इस विषय पर चर्चा करने के लिए चैट पर ले जा सकता है , तो मैं वास्तव में इसकी सराहना करूंगा।

@DeadMG, क्या आप जानते हैं कि कॉम्बिनेटर को क्या करना चाहिए? यह COMBINE को माना जाता है। परिभाषा के अनुसार, कॉम्बिनेटर बिना किसी फ्री वैरिएबल के एक फंक्शन है।
एसके-तर्क

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

@DeadMG, एक परिभाषा क्रिस्टल स्पष्ट है। कोई मुक्त चर नहीं। मैं किसी भी भाषा को "कार्यात्मक पर्याप्त" मानता हूं यदि वाई-कॉम्बिनेटर को परिभाषित करना संभव है (ठीक से, आपके तरीके से नहीं)। एक बड़ा "+" है यदि यह एस, के और आई कॉम्बिनेटर के माध्यम से परिभाषित करना संभव है। अन्यथा भाषा पर्याप्त अभिव्यंजक नहीं है।
एसके-लॉजिक

4
@ एसके-तर्क: आप चैट में क्यों नहीं आते हैं , जैसे कि मॉडरेटर ने पूछा है? इसके अलावा, एक वाई-कॉम्बिनेटर एक वाई-कॉम्बिनेटर है, यह काम करता है या यह नहीं करता है। वाई-कॉम्बिनेटर का हास्केल संस्करण मूल रूप से इस एक के समान है, यह सिर्फ इतना है कि व्यक्त की गई अवस्था आपसे छिपी हुई है।
डेडएमजी

11

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

वास्तव में, मेमोरी लीक जीसीईडी भाषाओं में लिखे गए कार्यक्रमों में काफी अक्सर होती है, क्योंकि ये भाषाएं प्रोग्रामर को आलसी बना देती हैं, और उन्हें सुरक्षा का झूठा एहसास दिलाती हैं कि भाषा हमेशा किसी न किसी (जादुई रूप से) हर वस्तु का ख्याल रखेगी कि वे अब और सोचने की इच्छा मत करो।

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

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

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


4

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

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


1
@ मेसन व्हीलर, यहां तक ​​कि C ++ बहुत सीमित रूप के क्लोजर को लागू करता है। लेकिन लगभग एक उचित, आम तौर पर प्रयोग करने योग्य बंद नहीं है।
एसके-लॉजिक

1
तुम गलत हो। कोई जीसी आपको इस तथ्य से नहीं बचा सकता है कि आप स्टैक चर का संदर्भ नहीं दे सकते। और यह मजाकिया है- C ++ में, आप "एक पॉइंटर को डायनामिक रूप से आवंटित चर पर कॉपी कर सकते हैं जो उचित रूप से और स्वचालित रूप से नष्ट हो जाएगा" दृष्टिकोण भी ले जा सकता है।
डेडएमजी

1
@DeadMG, क्या आप नहीं देखते हैं कि आपका कोड किसी अन्य स्तर के माध्यम से निम्न स्तर की संस्थाओं को लीक कर रहा है जो आप शीर्ष पर बनाते हैं?
एसके-लॉजिक

1
@ एसके-लॉजिक: ठीक है, हमें शब्दावली की समस्या है। "वास्तविक बंद होने" की आपकी परिभाषा क्या है, और वे क्या कर सकते हैं कि डेल्फी के बंद नहीं हो सकते हैं? (और आपकी परिभाषा में मेमोरी प्रबंधन के बारे में कुछ भी शामिल है, लक्ष्य पोस्ट को आगे बढ़ा रहा है। आइए व्यवहार के बारे में बात करें, कार्यान्वयन विवरण नहीं।)
मेसन व्हीलर

1
@ एसके-लॉजिक: ... और क्या आपके पास ऐसी चीज़ का उदाहरण है जो सरल-अनपेक्षित-लैम्ब्डा-क्लोजर के साथ किया जा सकता है जो डेल्फी के समापन को पूरा नहीं कर सकता है?
मेसन व्हीलर

2

वास्तव में, अपनी खुद की मेमोरी का प्रबंधन करना बग का एक और संभावित स्रोत है।

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


3
चूकना freeसबसे बुरी बात नहीं है। प्रारंभिक freeबहुत अधिक विनाशकारी है।
हिरोइन

2
और डबल free!
मात्रा_देव

हेहे! मैं ऊपर की दोनों टिप्पणियों के साथ जाना चाहता हूँ। मैंने कभी भी इनमें से एक भी अपराध नहीं किया है (जहाँ तक मुझे पता है), लेकिन मैं देख सकता हूँ कि प्रभाव कितना भयानक हो सकता है। क्वांट_देव का जवाब यह सब कहता है - मेमोरी आवंटन और डी-आवंटन के साथ गलतियां खोजने और ठीक करने के लिए कुख्यात हैं।
दाऊद का कहना है कि मोनिका

1
यह एक पतन है। आप "जल्दी 1970" की तुलना "1990 के अंत में" कर रहे हैं। जेंटलमैन कैडेट उस समय अस्तित्व में है, जिस पर mallocऔर freeजाने के लिए गैर-जीसी तरीका था बेहद भी चीज के लिए उपयोगी होने के लिए धीमी रही। आपको इसकी तुलना आधुनिक गैर-जीसी दृष्टिकोण से करने की आवश्यकता है, जैसे आरएआईआई।
डेडएमजी

2
@ डेडएमजी आरएआई मैनुअल मेमोरी प्रबंधन नहीं है
क्वांट_देव

2

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


1

मुझे लगता है कि कचरा संग्रह को भाषा सुधार के लिए बहुत अधिक श्रेय मिलता है जिसका जीसी के साथ कोई लेना-देना नहीं है, प्रगति की एक बड़ी लहर का हिस्सा होने के अलावा अन्य कुछ भी नहीं है।

जीसी के बारे में एक ठोस लाभ मुझे पता है कि आप अपने कार्यक्रम में एक वस्तु को मुफ्त में सेट कर सकते हैं और यह जान सकते हैं कि जब सभी इसके साथ हो जाएंगे तो यह चले जाएंगे। आप इसे किसी अन्य कक्षा की विधि में पास कर सकते हैं और इसके बारे में चिंता नहीं कर सकते। आप परवाह नहीं करते हैं कि यह किन अन्य तरीकों से पास होता है, या अन्य वर्ग इसका क्या संदर्भ देते हैं। (मेमोरी लीक एक ऑब्जेक्ट को संदर्भित करने वाले वर्ग की जिम्मेदारी है, न कि उस वर्ग ने जो इसे बनाया है।)

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

तो यह एकमात्र GC लाभ है जिसके बारे में मुझे पता है, लेकिन मैं इसके बिना नहीं रह सकता। मुझे नहीं लगता कि किसी भी तरह का ओओपी इसके बिना उड़ान भरेगा।


1
मेरे सिर के ऊपर से, डेल्फी और सी ++ दोनों बिना किसी जीसी के ओओपी भाषाओं के रूप में काफी सफल रहे हैं। आपको "नियंत्रण संदर्भों से बाहर" को रोकने की आवश्यकता है जो थोड़ा अनुशासन है। यदि आप एकल स्वामित्व सिद्धांत को समझते हैं, (मेरा उत्तर देखें), तो आप जिन समस्याओं के बारे में बात कर रहे हैं, वे कुल गैर-मुद्दे बन जाते हैं।
मेसन व्हीलर

@MasonWheeler: जब मालिक की वस्तु को मुक्त करने का समय आता है, तो उसे उन सभी स्थानों को जानना होगा जो उसके स्वामित्व वाली वस्तुओं को संदर्भित करते हैं। इस जानकारी को बनाए रखना और संदर्भों को हटाने के लिए इसका उपयोग करना मेरे लिए एक बहुत बड़ा काम लगता है। मैंने अक्सर पाया कि संदर्भ अभी तक काफी हद तक साफ नहीं किए जा सके हैं। मुझे स्वामी को हटाए जाने के रूप में चिह्नित करना था, फिर समय-समय पर इसे देखने के लिए जीवन में लाएं कि क्या यह सुरक्षित रूप से खुद को मुक्त कर सकता है। मैंने डेल्फी का उपयोग कभी नहीं किया है, लेकिन निष्पादन दक्षता में एक छोटे से बलिदान के लिए C # / Java ने मुझे C ++ के विकास के समय में बड़ा बढ़ावा दिया। (जीसी के कारण सभी नहीं, लेकिन इसने मदद की।)
राल्फचैपिन

1

फिजिकल लीक्स

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

सी एंड से आ रहा है, जो मेमोरी प्रबंधन को मैनुअल के रूप में बनाता है और जितना संभव हो उतना उच्चारित किया जाता है ताकि हम चरम सीमाओं (सी ++ ज्यादातर जीसी के बिना मेमोरी प्रबंधन को स्वचालित कर सकें), मैं जीसी से तुलना करने के अर्थ में "वास्तव में नहीं" कहूंगा। लीक पर आता है । एक शुरुआत और कभी-कभी एक समर्थक भी freeदिए गए के लिए लिखना भूल सकता है malloc। यह निश्चित रूप से होता है।

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

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

जब जीसी के छद्म रूप (संदर्भ गिनती, उदाहरण) जैसे कुछ के बिना यह भी मुश्किल होता है, जब किसी वस्तु के जीवनकाल को किसी अन्य प्रकार के आस्थगित / अतुल्यकालिक प्रसंस्करण के लिए विस्तारित करने की आवश्यकता होती है, शायद।

दंगल पॉइंट्स

स्मृति प्रबंधन के अधिक मैनुअल रूपों के साथ वास्तविक मुद्दा मेरे लिए लीक नहीं है। C या C ++ में लिखे गए कितने मूल एप्लिकेशन हैं जो हमें पता है कि वास्तव में लीक हैं? क्या लिनक्स कर्नेल लीक है? माई एसक्यूएल? क्रायंगाइन 3? डिजिटल ऑडियो वर्कस्टेशन और सिंथेसाइज़र? क्या जावा वीएम लीक (यह देशी कोड में लागू किया गया है)? फोटोशॉप?

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

मेरे लिए मुद्दा हमेशा सुरक्षा का था। यहां तक ​​कि जब हम freeएक पॉइंटर के माध्यम से मेमोरी करते हैं , तो यदि संसाधन में कोई अन्य पॉइंटर्स हैं, तो वे झूलने (अमान्य) पॉइंटर्स बन जाएंगे।

जब हम उन झूलने वाले बिंदुओं के पॉइट्स तक पहुंचने का प्रयास करते हैं, तो हम अनिर्धारित व्यवहार में भाग लेते हैं, हालांकि लगभग हमेशा एक सेगफॉल्ट / एक्सेस उल्लंघन एक कठिन, तत्काल दुर्घटना का कारण बनता है।

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

... और ऐसा इसलिए है क्योंकि आप जीसी का उपयोग करते हैं या नहीं, इसकी परवाह किए बिना संसाधन प्रबंधन कठिन है। व्यावहारिक अंतर अक्सर या तो लीक हो रहा है (जीसी) या क्रैश (जीसी के बिना) एक गलती के कारण संसाधन कुप्रबंधन के कारण।

संसाधन प्रबंधन: कचरा संग्रह

जटिल संसाधन प्रबंधन एक कठिन, मैन्युअल प्रक्रिया है, चाहे जो भी हो। जीसी यहां कुछ भी स्वचालित नहीं कर सकता है।

चलो एक उदाहरण लेते हैं जहां हमारे पास यह वस्तु है, "जो"। जो को कई संगठनों द्वारा संदर्भित किया जाता है, जिसमें वह एक सदस्य है। हर महीने या तो वे अपने क्रेडिट कार्ड से सदस्यता शुल्क निकालते हैं।

यहाँ छवि विवरण दर्ज करें

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

यहाँ छवि विवरण दर्ज करें

... लेकिन रुकिए, हम कचरा संग्रहण का उपयोग कर रहे हैं। जो के लिए हर मजबूत संदर्भ उसे चारों ओर रखेगा। इसलिए हम उनसे उन संगठनों के संदर्भ भी हटा देते हैं, जिनसे वह संबंध रखते हैं (उन्हें अनसब्सक्राइब करते हुए)।

यहाँ छवि विवरण दर्ज करें

... व्हाट्सएप को छोड़कर, हम उनकी पत्रिका सदस्यता रद्द करना भूल गए! अब जो स्मृति में रहता है, हमें परेशान करता है और संसाधनों का उपयोग करता है, और पत्रिका कंपनी हर महीने जोए की सदस्यता की प्रक्रिया को जारी रखती है।

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

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

संसाधन प्रबंधन: मैनुअल

अब आइए उस विकल्प पर विचार करें जहां हम जो और मैनुअल मेमोरी मैनेजमेंट जैसे पॉइंटर्स का उपयोग करते हैं, जैसे:

यहाँ छवि विवरण दर्ज करें

ये नीले लिंक जो के जीवनकाल का प्रबंधन नहीं करते हैं। यदि हम उसे पृथ्वी के सामने से हटाना चाहते हैं, तो हम स्वयं उसे नष्ट करने का अनुरोध करते हैं, जैसे:

यहाँ छवि विवरण दर्ज करें

अब जो सामान्य रूप से हमें सभी स्थानों पर झूलने वाले बिंदुओं के साथ छोड़ देगा, तो चलो जो को इंगित करने वाले बिंदुओं को हटा दें।

यहाँ छवि विवरण दर्ज करें

... वूप्स, हमने फिर से वही गलती की और जो की पत्रिका सदस्यता को सदस्यता समाप्त करना भूल गए!

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

यह वही बुनियादी संसाधन कुप्रबंधन गलती है जहाँ डेवलपर मैन्युअल रूप से सभी बिंदुओं / संदर्भों को हटाना भूल जाता है, जिससे मूल अनुप्रयोगों में बहुत सारे क्रैश हो सकते हैं। वे स्मृति को अधिक देर तक नहीं चलाते हैं क्योंकि वे आमतौर पर चलते हैं क्योंकि वे अक्सर इस मामले में एकमुश्त दुर्घटना करेंगे।

असली दुनिया

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

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

क्रैश बनाम लीक

अब कौन सा बदतर है? एक तत्काल दुर्घटना, या एक खामोश स्मृति रिसाव जहां जो बस रहस्यमय तरीके से आसपास रहती है?

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

इस मामले में, एक कठिन दुर्घटना जो डिबगिंग करते समय तुरंत दिखाई देती है, जो आपके द्वारा की गई गलती को इंगित करती है, वास्तव में सिर्फ एक लीक सॉफ्टवेयर के लिए बेहतर हो सकता है जो आपके परीक्षण प्रक्रिया के रडार के नीचे भी उड़ सकता है।

दूसरी तरफ, यदि यह एक मिशन-क्रिटिकल सॉफ्टवेयर है, जहां प्रदर्शन लक्ष्य नहीं है, बस किसी भी तरह से दुर्घटनाग्रस्त नहीं हो सकता है, तो लीक करना वास्तव में बेहतर हो सकता है।

कमजोर संदर्भ

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

दुर्भाग्य से कमजोर संदर्भों का उपयोग लगभग उतना नहीं किया जाता है जितना संभवत: उनका उपयोग किया जाना चाहिए, इसलिए अक्सर बहुत सारे जटिल जीसी अनुप्रयोगों को लीक होने की संभावना हो सकती है, भले ही वे एक जटिल सी अनुप्रयोग की तुलना में संभवतः बहुत कम दुर्घटनाग्रस्त हों, जैसे।

किसी भी मामले में, जीसी आपके जीवन को आसान या कठिन बनाता है या नहीं, यह इस बात पर निर्भर करता है कि लीक से बचने के लिए आपके सॉफ्टवेयर के लिए यह कितना महत्वपूर्ण है, और इस तरह के जटिल संसाधन प्रबंधन से संबंधित है या नहीं।

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

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


-1

स्मृति से निपटने के दौरान C ++ प्रोग्रामर के सामने आने वाली समस्याओं की एक सूची है:

  1. स्टैक आवंटित मेमोरी में स्कोपिंग की समस्या होती है: यह जीवनकाल उस फ़ंक्शन के बाहर का विस्तार नहीं करता है जहां इसे आवंटित किया गया था। इस समस्या के तीन मुख्य समाधान हैं: मेमोरी को ढेर करना, और कॉल स्टैक में आवंटन बिंदु को ऊपर की ओर ले जाना या अंदर की वस्तुओं से आवंटित करना। ।
  2. Sizeof की समस्या स्टैक में आवंटित की गई है और ऑब्जेक्ट के अंदर से और आंशिक रूप से आवंटित मेमोरी को आवंटित करना है: मेमोरी ब्लॉक का आकार रनटाइम पर नहीं बदल सकता है। समाधान ढेर स्मृति सरणियों, संकेत और पुस्तकालयों और कंटेनर हैं।
  3. परिभाषा की समस्या का आदेश तब होता है जब अंदर की वस्तुओं से आवंटित किया जाता है: कार्यक्रम के अंदर की कक्षाओं को सही क्रम में होना चाहिए। समाधान एक पेड़ पर निर्भरता को सीमित कर रहे हैं और कक्षाओं को फिर से व्यवस्थित कर रहे हैं और आगे की घोषणाओं का उपयोग नहीं कर रहे हैं, और संकेत और ढेर स्मृति और आगे की घोषणाओं का उपयोग कर रहे हैं।
  4. इनसाइड-आउटसाइड समस्या ऑब्जेक्ट आवंटित मेमोरी में है। ऑब्जेक्ट्स के अंदर मेमोरी एक्सेस दो भागों में विभाजित है, कुछ मेमोरी एक ऑब्जेक्ट के अंदर है और अन्य मेमोरी इसके बाहर है, और प्रोग्रामर को इस निर्णय के आधार पर रचना या संदर्भों का उपयोग करने के लिए सही ढंग से चुनने की आवश्यकता है। समाधान निर्णय सही ढंग से कर रहे हैं, या संकेत और ढेर स्मृति।
  5. पुनरावर्ती ऑब्जेक्ट्स समस्या ऑब्जेक्ट आवंटित स्मृति में है। वस्तुओं का आकार अनंत हो जाता है यदि एक ही वस्तु को अपने अंदर रखा जाए, और समाधान संदर्भ, ढेर स्मृति और संकेत हैं।
  6. स्वामित्व ट्रैकिंग समस्या ढेर आबंटित मेमोरी में होती है, पॉइंटर आबंटित मेमोरी के पते वाले पॉइंटर को आबंटन बिंदु से लेकर डीलक्लोलेशन बिंदु तक पास करना होता है। समाधान में स्टैक आवंटित मेमोरी, ऑब्जेक्ट-एलोएटेड मेमोरी, ऑटो_प्ट्र, शेयर्ड_प्ट्र, यूनीक_प्ट्र, स्टैडिबिब कंटेनर हैं।
  7. स्वामित्व डुप्लीकेशन समस्या ढेर आवंटित मेमोरी में है: डीलक्लोकेशन केवल एक बार किया जा सकता है। समाधान में स्टैक आवंटित मेमोरी, ऑब्जेक्ट-एलाय्ड मेमोरी, ऑटो_प्ट्र, शेयर_एप्ट्र, यूनीक_प्ट्र, स्टडलिब कंटेनर हैं।
  8. नल पॉइंटर समस्या ढेर आवंटित मेमोरी में है: पॉइंटर्स को NULL होने की अनुमति है जो रनटाइम पर कई ऑपरेशन क्रैश कर रहे हैं। समाधान स्टैक मेमोरी, ऑब्जेक्ट-आवंटित मेमोरी और हीप क्षेत्रों और संदर्भों का सावधानीपूर्वक विश्लेषण है।
  9. मेमोरी लीक की समस्या ढेर आवंटित मेमोरी में है: हर आवंटित मेमोरी ब्लॉक के लिए कॉल डिलीट को भूल जाना। समाधान वेलग्रिंड जैसे उपकरण हैं।
  10. स्टैक ओवरफ्लो समस्या पुनरावर्ती फ़ंक्शन कॉल के लिए है जो स्टैक मेमोरी का उपयोग कर रहे हैं। सामान्य रूप से स्टैक का आकार पुनरावर्ती एल्गोरिदम के मामले को छोड़कर, संकलन समय पर पूरी तरह से निर्धारित किया जाता है। ओएस के स्टैक आकार को गलत तरीके से परिभाषित करना भी अक्सर इस समस्या का कारण बनता है क्योंकि स्टैक स्थान के आवश्यक आकार को मापने का कोई तरीका नहीं है।

जैसा कि आप देख सकते हैं, ढेर स्मृति कई मौजूदा समस्याओं को हल कर रही है, लेकिन यह अतिरिक्त जटिलता का कारण बनती है। जीसी को उस जटिलता के हिस्से को संभालने के लिए डिज़ाइन किया गया है। (क्षमा करें यदि कुछ समस्या के नाम इन समस्याओं के लिए सही नाम नहीं हैं - कभी-कभी सही नाम का पता लगाना मुश्किल होता है)


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