अगर स्मार्ट पॉइंटर्स हैं तो गारबेज कलेक्शन क्यों


67

इन दिनों, कई भाषाओं में कचरा एकत्र किया जाता है। यह तीसरे पक्ष द्वारा C ++ के लिए भी उपलब्ध है। लेकिन C ++ में RAII और स्मार्ट पॉइंटर्स हैं। तो कचरा संग्रहण का उपयोग करने की क्या बात है? क्या यह कुछ अतिरिक्त कर रहा है?

और अन्य भाषाओं में C # की तरह, यदि सभी संदर्भों को स्मार्ट पॉइंटर्स (RAII को अलग रखते हुए), विनिर्देशन और कार्यान्वयन द्वारा माना जाता है, तो क्या अभी भी कचरा बीनने वालों की कोई आवश्यकता होगी? यदि नहीं, तो ऐसा क्यों नहीं है?


1
इस सवाल को पूछने के बाद मुझे एक बात समझ में आई- स्मार्ट पॉइंटर्स को ऑटोमैटिक डीक्लोकेशन मैनेज करने के लिए RAII की जरूरत है
गुलशन

8
स्मार्ट पॉइंटर्स का मतलब जीसी के लिए RAII का उपयोग करना है;)
डारियो

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

जवाबों:


67

तो, कचरा संग्रह का उपयोग करने की बात क्या है?

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

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

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

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


23
विश्वास नहीं कर सकता है कि इस उत्तर ने शीर्ष उत्तर को समाप्त कर दिया। यह C ++ स्मार्ट पॉइंटर्स की समझ की कुल कमी को दर्शाता है और यह दावा करता है कि वास्तविकता के साथ सिंक से बहुत बाहर हैं जो कि बस हास्यास्पद है। सबसे पहले, स्मार्ट पॉइंटर जो C ++ कोड के एक अच्छी तरह से डिज़ाइन किए गए टुकड़े में सबसे प्रमुख होगा, अद्वितीय सूचक है, न कि शेयर पॉइंटर। en.cppreference.com/w/cpp/memory/unique_ptr और दूसरी बात, मैं विश्वास नहीं कर सकता कि आप वास्तव में 'प्रदर्शन' के फायदे और स्मार्ट पॉइंटर्स पर गैर-नियतात्मक कचरा संग्रह के वास्तविक समय के फायदे का दावा कर रहे हैं।
user1703394

4
@ user1703394 यह प्रतीत होता है कि उत्तर देने वाले ने मन में संकेत साझा किया था (सही या गलत, मुझे यकीन नहीं है कि ओपी क्या सुझाव दे रहा है), जो गैर निर्धारक कचरा संग्रह से कम प्रदर्शन कर रहे हैं।
नाथन कूपर

8
ये सभी स्ट्रॉ मैन तर्क हैं और केवल मान्य हैं यदि आप या तो पूरी तरह से वास्तविक प्रश्न को अनदेखा करते हैं या विभिन्न प्रकार के स्मार्ट पॉइंटर्स के वास्तविक उपयोग पैटर्न को अनदेखा करते हैं। सवाल स्मार्ट पॉइंटर्स का था। Yes shared_ptr एक स्मार्ट पॉइंटर है और Yes shared_ptr स्मार्ट पॉइंटर्स का सबसे महंगा है, लेकिन नहीं, किसी भी प्रदर्शन तर्क को प्रासंगिक बनाने के करीब कहीं भी उनके व्यापक उपयोग के लिए कोई वास्तविक तर्क नहीं है। गंभीरता से, इस जवाब को संदर्भ गिनती पर एक प्रश्न के लिए स्थानांतरित किया जाना चाहिए। मैं एक अच्छे स्मार्ट पॉइंटर प्रश्न के खराब संदर्भ गिनती का उत्तर देता हूं।
user1703394

4
"स्मार्ट पॉइंटर्स एक व्यापक अवधारणा नहीं हैं", गंभीरता से? आपको पता नहीं है कि यह कथन आपके द्वारा अब तक किए गए सभी संभावित मान्य तर्कों को कितना कम कर देता है। शायद Rust के स्वामित्व पर एक नज़र डालें और शब्दार्थ को आगे बढ़ाएँ : koerbitz.me/posts/… यह C ++ के साथ ऐतिहासिक अनुभव वाले लोगों के लिए इस तथ्य को याद रखना आसान है कि C ++ 11 / C ++ 14 अपने मेमोरी मॉडल के साथ, बेहतर स्मार्ट पॉइंटर्स और मूव शब्दार्थ अपने पूर्ववर्तियों की तुलना में एक अलग जानवर है। रस्ट कैसे करता है, इस पर एक नजर है, यह सी ++ की तुलना में क्लीनर है और ताजा परिप्रेक्ष्य प्रदान करता है।
user1703394

6
@ user1703394: "विध्वंसक होने के कारण बिना रुके, गैर-स्मृति संसाधनों के लिए उपयोग किए जा रहे RAII की एक दुर्भाग्यपूर्ण संपत्ति है"। नहीं, गैर-स्मृति संसाधनों से इसका कोई लेना-देना नहीं है।
जॉन हैरोप

63

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

उस सवाल के जवाब के कुछ जोड़े हैं। सबसे महत्वपूर्ण पहला:

  1. आप यह सुनिश्चित करते हैं कि सभी कोड इसे इंटरप्रेट करने के लिए उपयोग कर सकते हैं। यह है, मुझे लगता है, कोड का पुन: उपयोग और कोड साझा करने का बड़ा कारण वास्तव में जावा / सी # / पायथन / रूबी तक नहीं था। पुस्तकालयों को संवाद करने की आवश्यकता है, और केवल विश्वसनीय साझा भाषा उनके पास है जो भाषा में ही कल्पना है (और, एक हद तक, इसकी मानक पुस्तकालय)। यदि आपने कभी C ++ में पुस्तकालयों का पुन: उपयोग करने का प्रयास किया है, तो संभवतः आपको भयावह दर्द का अनुभव हुआ है जो किसी भी मानक स्मृति शब्दार्थ का कारण नहीं बनता है। मैं कुछ देयता के लिए एक संरचना पारित करना चाहता हूं। क्या मैं एक संदर्भ पास करूं? सूचक? scoped_ptr?smart_ptr? क्या मैं स्वामित्व से गुजर रहा हूं, या नहीं? क्या इसका संकेत देने का कोई तरीका है? क्या होगा यदि दायित्व आवंटित करने की आवश्यकता है? क्या मुझे इसे एक आबंटक देना होगा? मेमोरी प्रबंधन को भाषा का हिस्सा नहीं बनाने से, C ++ पुस्तकालयों के प्रत्येक जोड़े को अपनी विशिष्ट रणनीति पर बातचीत करने के लिए मजबूर करता है, और उन सभी को सहमत करना वास्तव में कठिन है। जीसी एक पूर्ण गैर-मुद्दा बनाता है।

  2. आप इसके चारों ओर सिंटैक्स डिज़ाइन कर सकते हैं। चूँकि C ++ मेमोरी-मैनेजमेंट को अतिक्रमण नहीं करता है, इसलिए इसे उपयोगकर्ता-स्तरीय कोड को सभी विवरणों को व्यक्त करने के लिए सिंटैक्टिक हुक की एक सीमा प्रदान करनी होती है। आपके पास पॉइंटर्स, रेफरेंस, constडीरेफरिंग ऑपरेटर, इनडायरेक्ट ऑपरेटर्स, एड्रेस-इन आदि हैं। यदि आप मेमोरी मैनेजमेंट को भाषा में ही रोल करते हैं, तो सिंटैक्स को इसके चारों ओर डिज़ाइन किया जा सकता है। वे सभी ऑपरेटर गायब हो जाते हैं और भाषा क्लीनर और सरल हो जाती है।

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


शानदार जवाब! अगर केवल मैं एक से अधिक बार उत्थान कर सकता हूं ...
डीन हार्डिंग

10
यह ध्यान देने योग्य है कि कचरा संग्रह वास्तव में सी # भाषा में ही लागू नहीं होता है, लेकिन .NET फ्रेमवर्क में , विशेष रूप से सामान्य भाषा रनटाइम (सीएलआर)।
रॉबर्ट हार्वे

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

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

34

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

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

स्मार्ट पॉइंटर्स केवल किसी भी संरचना को संदर्भित करते हैं जो एक साधारण पॉइंटर की तरह व्यवहार करता है लेकिन इसमें कुछ अतिरिक्त कार्यक्षमता जुड़ी हुई है। इनमें शामिल हैं, लेकिन यह केवल डीलक्लोकेशन तक ही सीमित नहीं है, बल्कि कॉपी-ऑन-राइट, बाउंड चेक, ...

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

लेकिन विचार की ट्रेन निम्नलिखित तरीके से जाती है:

  1. कचरा संग्रह एक अच्छी बात है, क्योंकि यह सुविधाजनक है और मुझे कम चीजों का ध्यान रखना है
  2. इसलिए: मैं अपनी भाषा में कचरा संग्रह चाहता हूं
  3. अब, मेरी भाषा में GC कैसे प्राप्त कर सकता है?

बेशक, आप इसे शुरू से ही इस तरह से डिजाइन कर सकते हैं। C # को कचरा एकत्र करने के लिए डिज़ाइन किया गया था , इसलिए बस newआपकी वस्तु और इसे तब जारी किया जाएगा जब संदर्भ दायरे से बाहर हो जाएंगे। यह कैसे किया जाता है संकलक तक।

लेकिन C ++ में, वहाँ कोई कचरा संग्रह नहीं था। यदि हम कुछ पॉइंटर को आवंटित करते हैं int* p = new int;और यह दायरे से बाहर हो जाता है, तो pखुद को स्टैक से हटा दिया जाता है, लेकिन कोई भी आवंटित मेमोरी का ध्यान नहीं रखता है।

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

यह सभी अत्यधिक सी ++ विशिष्ट है: ऑपरेटर ओवरलोडिंग, टेम्प्लेट, डिस्ट्रक्टर्स, ... इस विशेष भाषा की स्थिति में, आपको स्मार्ट पॉइंटर्स विकसित किए हैं जो आपको जीसी के साथ प्रदान करना चाहते हैं।

लेकिन अगर आप शुरू से ही जीसी के साथ एक भाषा डिजाइन करते हैं, तो यह केवल एक कार्यान्वयन विवरण है। आप सिर्फ कहते हैं कि वस्तु को साफ किया जाएगा और संकलक आपके लिए ऐसा करेगा।

C ++ जैसे स्मार्ट पॉइंटर्स शायद C # जैसी भाषाओं में भी संभव नहीं होंगे, जिनका कोई नियतकालिक विनाश नहीं होता है (C # इसके आस-पास .Dispose()कुछ वस्तुओं पर कॉल करने के लिए सिंथैटिक शुगर प्रदान करके काम करता है )। अप्रशिक्षित संसाधनों को अंततः जीसी द्वारा पुनः प्राप्त किया जाएगा, लेकिन यह अपरिभाषित है कि वास्तव में ऐसा कब होगा।

और यह, बदले में, जीसी को अपने काम को अधिक कुशल करने की अनुमति दे सकता है। स्मार्ट पॉइंटर्स की तुलना में भाषा में गहराई से निर्मित होने के कारण, जो इसके शीर्ष पर सेट होते हैं। .NET GC उदाहरण के तौर पर मेमोरी संचालन में देरी कर सकता है और ब्लॉक में प्रदर्शन कर उन्हें सस्ता बना सकता है या यहां तक कि कितनी बार वस्तुओं पर आधारित दक्षता बढ़ाने के लिए मेमोरी को स्थानांतरित कर सकता है। पहुंच रहे हैं।


C # के माध्यम से नियतात्मक विनाश का एक रूप है IDisposableऔर using। लेकिन इसके लिए थोड़ी सी प्रोग्रामर कोशिश करनी पड़ती है, यही वजह है कि इसका इस्तेमाल आमतौर पर बहुत ही कम संसाधनों जैसे डेटाबेस कनेक्शन हैंडल के लिए किया जाता है।
जेएसबी JS

7
@JSBangs: बिल्कुल सही। जिस तरह C ++, GCII प्राप्त करने के लिए RAII के चारों ओर स्मार्ट पॉइंटर्स बनाता है, C # दूसरे तरीके से जाता है और RAII प्राप्त करने के लिए GC के आसपास "स्मार्ट डिस्पोज़र्स" का निर्माण करता है;) वास्तव में, यह शर्म की बात है कि CII में RAII इतना मुश्किल है; अपवाद के लिए यह बहुत अच्छा है- सुरक्षित संसाधन हैंडलिंग। F # उदाहरण के लिए IDisposableपारंपरिक let ident = valueद्वारा प्रतिस्थापित करके एक सरल वाक्यविन्यास की कोशिश करता है use ident = value...
Dario

@ डारियो: "C # दूसरे तरीके से जाता है और RAII प्राप्त करने के लिए GC के आसपास 'स्मार्ट डिस्पोजर्स' बनाता है।" C # में RAII का usingकचरा संग्रहण से कोई लेना-देना नहीं है, यह केवल एक फ़ंक्शन को कॉल करता है जब C ++ में डिस्ट्रक्टर्स की तरह एक चर दायरे से बाहर हो जाता है।
जॉन हैरोप

1
@ जॉन हैरोप: कृपया क्या? आपके द्वारा दिए गए कथन में सादे C ++ विध्वंसक के बारे में है, बिना किसी संदर्भ के गिनती / स्मार्ट पॉइंटर्स / कचरा संग्रह शामिल है।
डारियो

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

4

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

  1. स्मार्ट पॉइंटर्स चक्रीय कचरा एकत्र नहीं कर सकते हैं; कचरा संग्रह कर सकते हैं
  2. स्मार्ट पॉइंटर्स, आवेदन थ्रेड पर रेफ़रिंग, डेफ़रिंग और डीलक्लोकेशन के सभी काम करते हैं; कचरा संग्रह की आवश्यकता नहीं है

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

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

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

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


6
@ टोम: स्मार्ट पॉइंटर्स के बारे में विवरण के लिए डारियो के जवाब पर एक नज़र है। स्मार्ट पॉइंटर्स के फायदों के लिए - जब संसाधनों को नियंत्रित करने के लिए (न केवल मेमोरी) का उपयोग किया जाता है, तो निर्धारक डीलॉलेशन एक बहुत बड़ा लाभ हो सकता है। वास्तव में, यह इतना महत्वपूर्ण साबित हुआ है कि Microsoft ने usingब्लॉक को C # के बाद के संस्करणों में पेश किया है। इसके अलावा, GCs के गैर-व्यवहारिक व्यवहार को वास्तविक समय प्रणालियों में मना किया जा सकता है (यही वजह है कि GCs का वहां उपयोग नहीं किया जाता है)। इसके अलावा, यह मत भूलो कि GCs सही पाने के लिए इतने जटिल हैं कि अधिकांश वास्तव में मेमोरी लीक करते हैं और काफी अक्षम हैं (जैसे बोहम ...)।
कोनराड रूडोल्फ

6
GCs के nondeterminism है, मुझे लगता है, एक लाल हेरिंग का एक सा है - GC सिस्टम हैं जो realtime उपयोग के लिए उपयुक्त हैं (जैसे IBM के Recycler), भले ही आप डेस्कटॉप और सर्वर VMs में देख रहे हैं। इसके अलावा, स्मार्ट पॉइंटर्स का उपयोग करने का मतलब है कि मॉलोक / फ्री का उपयोग करना, और फ्री लिस्ट को सर्च करने की आवश्यकता के कारण मॉलोक के पारंपरिक कार्यान्वयन नोन्डेटर्मिनिस्टिक हैं। चलती जीसी प्रणालियों में मॉलॉक / मुक्त प्रणालियों की तुलना में अधिक नियतात्मक आवंटन समय होता है, हालांकि निश्चित रूप से कम नियतांक से निपटने के समय।
टॉम एंडरसन

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

8
@ जॉन: निश्चित रूप से बकवास नहींBugzilla.novell.com/show_bug.cgi?id=621899 या, आम तौर पर: flyfrogblog.blogspot.com/2009/01/… यह सर्वविदित है और सभी रूढ़िवादी जीसी की संपत्ति है।
कोनराड रुडोल्फ

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

3

कचरा संग्रह शब्द का तात्पर्य है कि संग्रह करने के लिए कोई कचरा है। C ++ में स्मार्ट पॉइंटर्स कई फ्लेवर्स में आते हैं, सबसे महत्वपूर्ण बात यह है कि unique_ptr। Unique_ptr मूल रूप से एक एकल स्वामित्व और स्कूपिंग निर्माण है। कोड के एक अच्छी तरह से डिज़ाइन किए गए टुकड़े में, अधिकांश ढेर आवंटित सामान सामान्य रूप से अद्वितीय_पार्ट स्मार्ट पॉइंटर्स के पीछे रहते हैं और उन संसाधनों के स्वामित्व को हर समय अच्छी तरह से परिभाषित किया जाएगा। Unique_ptr में शायद ही कोई ओवरहेड है और unique_ptr अधिकांश मैनुअल मेमोरी प्रबंधन समस्याओं को दूर करता है जो परंपरागत रूप से प्रबंधित भाषाओं में लोगों को हटाते हैं। अब जबकि समवर्ती रूप से चलने वाले अधिक कोर अधिक सामान्य होते जा रहे हैं, डिजाइन सिद्धांत जो किसी भी समय अद्वितीय और अच्छी तरह से परिभाषित स्वामित्व का उपयोग करने के लिए कोड चलाते हैं, प्रदर्शन के लिए अधिक महत्वपूर्ण हो जाते हैं।

यहां तक ​​कि एक अच्छी तरह से डिज़ाइन किए गए कार्यक्रम में, विशेष रूप से बहु थ्रेडेड वातावरणों में, साझा डेटा संरचनाओं के बिना सब कुछ व्यक्त नहीं किया जा सकता है, और उन डेटा संरचनाओं के लिए जिन्हें वास्तव में आवश्यकता होती है, थ्रेड्स को संवाद करने की आवश्यकता होती है। C ++ में RAII एकल थ्रेडेड सेटअप में जीवन भर की चिंताओं के लिए बहुत अच्छी तरह से काम करता है, एक बहु थ्रेडेड सेटअप में वस्तुओं का जीवनकाल पूरी तरह से पदानुक्रमित रूप से परिभाषित नहीं हो सकता है। इन स्थितियों के लिए, share_ptr का उपयोग समाधान का एक बड़ा हिस्सा प्रदान करता है। आप किसी संसाधन का साझा स्वामित्व बनाते हैं और यह C ++ में एकमात्र स्थान है जहां हम कचरा देखते हैं, लेकिन इतनी कम मात्रा में कि एक उचित डिज़ाइन किया गया c ++ प्रोग्राम को साझा-ptr के साथ 'कूड़े' के संग्रह को लागू करने के लिए अधिक माना जाना चाहिए, पूर्ण विकसित कचरा संग्रह अन्य भाषाओं में लागू किया गया। C ++ में बस इतना 'कचरा' नहीं है

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

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


1
क्या इसका मतलब Rustकचरा संग्रहण की आवश्यकता नहीं है?
गुलशन

1
@ गुलशन रस्ट बहुत कम भाषाओं में से एक है जो सुरक्षित यूनिक पॉइंटर्स का समर्थन करती है।
कोडइन्चोस

2

अधिकांश स्मार्ट पॉइंटर्स को संदर्भ गिनती का उपयोग करके कार्यान्वित किया जाता है। यही है, प्रत्येक स्मार्ट पॉइंटर जो ऑब्जेक्ट को संदर्भित करता है, ऑब्जेक्ट रेफरेंस काउंट को बढ़ाता है। जब वह गिनती शून्य हो जाती है, तो वस्तु जारी हो जाती है।

समस्या यह है कि यदि आपके पास परिपत्र संदर्भ हैं। यही है, A में B का संदर्भ है, B के पास C का संदर्भ है और C के पास A का संदर्भ है। यदि आप स्मार्ट पॉइंटर्स का उपयोग कर रहे हैं, तो A, B & C से जुड़ी मेमोरी को खाली करने के लिए आपको मैन्युअल रूप से उपयोग करने की आवश्यकता है। वहाँ एक "ब्रेक" परिपत्र संदर्भ (जैसे weak_ptrC ++ में उपयोग ) में मिलता है।

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

कि रास्ते में, वृत्तीय संदर्भ में कोई फर्क नहीं है किसी भी अधिक - जब तक न ए, बी और सी हैं पहुंचा जा सकता है, स्मृति पुनः दावा किया जा सकता है।

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

बेशक, C ++ में ढेर-आवंटित मेमोरी की मात्रा आमतौर पर C # / NET जैसी संदर्भ-भारी भाषा से कम है। लेकिन यह वास्तव में एक कचरा-संग्रह बनाम स्मार्ट पॉइंटर्स मुद्दा नहीं है।

किसी भी मामले में, मुद्दा कट-एंड-ड्राई नहीं है जो दूसरे से बेहतर है। उनमें से प्रत्येक के फायदे और नुकसान हैं।


2

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

C ++ (w / o any GC) में वस्तुओं का एक बड़ा गुच्छा आवंटित करने के लिए प्रयास करें, "हैलो" प्रिंट करें, फिर उन्हें हटा दें। आपको आश्चर्य होगा कि वस्तुओं को मुक्त करने में कितना समय लगता है।

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


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

हां, यकीन है, जीसी बहुत अधिक आरामदायक है। (विशेष रूप से शुरुआती लोगों के लिए: कोई स्वामित्व की समस्या नहीं है, यहां तक ​​कि कोई भी ऑपरेटर नहीं है।)
ern0

3
@ ern0: नहीं। (संदर्भ गिनती) स्मार्ट पॉइंटर्स का संपूर्ण बिंदु यह है कि कोई स्वामित्व समस्या नहीं है और कोई हटाने वाला ऑपरेटर नहीं है।
कोनराड रुडोल्फ

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

1
डील्लोकेशन अक्सर "पृष्ठभूमि में" नहीं किया जाता है, बल्कि सभी अग्रभूमि धागे को रोक देता है। बैच-मोड कचरा-संग्रह आम तौर पर एक प्रदर्शन जीत है, अग्रभूमि धागे के ठहराव के बावजूद, क्योंकि यह अप्रयुक्त स्थान को समेकित करने की अनुमति देता है। कोई कचरा-संग्रह और ढेर जमा करने की प्रक्रियाओं को अलग कर सकता है, लेकिन - विशेष रूप से ऐसे ढांचे में जो हैंडल के बजाय सीधे संदर्भ का उपयोग करते हैं - वे दोनों "स्टॉप-द-वर्ल्ड" प्रक्रिया करते हैं, और यह अक्सर उन्हें करने के लिए सबसे अधिक व्यावहारिक होता है। साथ में।
सुपरकैट

2

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

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

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

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

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


1
"आपके पास कुछ बिंदु पर डी-आवंटन गतिविधि का एक बड़ा विस्फोट होगा"। बेकर का ट्रेडमिल एक सुंदर वृद्धिशील कचरा संग्राहक का एक उदाहरण है। memorymanagement.org/glossary/t.html#treadmill
Jon Harrop

1

स्मार्ट पॉइंटर्स की नंबर एक सीमा यह है कि वे हमेशा परिपत्र संदर्भों के खिलाफ मदद नहीं करते हैं। उदाहरण के लिए, आपके पास ऑब्जेक्ट A है, B के लिए एक स्मार्ट पॉइंटर को स्टोर करना है और ऑब्जेक्ट B को ए से स्मार्ट पॉइंटर को स्टोर करना है। यदि वे दोनों पॉइंटर्स को रीसेट किए बिना एक साथ छोड़ दिए जाते हैं, तो वे कभी भी डीलॉक नहीं होंगे।

ऐसा इसलिए होता है क्योंकि एक स्मार्ट पॉइंटर को एक विशिष्ट क्रिया करनी होती है जो उपरोक्त परिदृश्य में नहीं होगी, क्योंकि दोनों ऑब्जेक्ट प्रोग्राम के लिए अप्राप्य हैं। कचरा संग्रह सामना करेगा - यह ठीक से पहचान लेगा कि वस्तुएं कार्यक्रम के लिए पुन: प्राप्य नहीं हैं और उन्हें एकत्र किया जाएगा।


1

यह एक स्पेक्ट्रम है

यदि आप प्रदर्शन पर कड़े प्रतिबंध नहीं लगाते हैं और पीस को लगाने के लिए तैयार हैं, तो आप सही निर्णय लेने के लिए आप पर सभी आरोपों के साथ विधानसभा या सी पर समाप्त हो जाएंगे और ऐसा करने की सभी स्वतंत्रता होगी, लेकिन इसके साथ , यह गड़बड़ करने के लिए सभी स्वतंत्रता:

"मैं आपको बताऊंगा कि आपको क्या करना है, आप इसे करें। मुझ पर विश्वास करें"।

कचरा संग्रह स्पेक्ट्रम का दूसरा छोर है। आपके पास बहुत कम नियंत्रण है, लेकिन इसकी देखभाल आपके लिए है:

"मैं आपको बताऊंगा कि मुझे क्या चाहिए, आप इसे पूरा करें"।

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

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


0

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

कचरा संग्रह के साथ उसके ऊपर सब कुछ, डेटा के संदर्भ जो स्थानांतरित हो सकते हैं, ढेर संकलन, आदि आदि उपरोक्त "मेमोरी चंक्स के साथ पता सूचक" प्रतिमान के साथ दिए गए प्रतिबंधों के भीतर काम कर रहे हैं। स्मार्ट पॉइंटर्स के साथ एक ही बात - आपको वास्तविक हार्डवेयर पर कोड रन बनाना होगा।

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