क्या गैर-नियतात्मक संसाधन-प्रबंधन एक लीक से हटकर है?


9

मैं जो देख सकता हूं, उसमें संसाधन-प्रबंधन के दो व्यापक रूप हैं: निर्धारक विनाश और स्पष्ट। पूर्व के उदाहरण C ++ डिस्ट्रक्टर्स और स्मार्ट पॉइंटर्स या पर्ल के DESTROY सब होंगे, जबकि बाद का एक उदाहरण रूबी के ब्लॉक-टू-मैनेजमेंट-संसाधनों का प्रतिमान या .NET का IDispose इंटरफ़ेस होगा।

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

मेरा प्रश्न यह है: स्मार्ट पॉइंटर्स या रेफरेंस-काउंटिंग गारबेज कलेक्शन सिस्टम के लिए विध्वंसक - लगभग एक ही चीज है - निहित और पारदर्शी संसाधन विनाश की अनुमति दें, क्या यह गैर-नियतात्मक प्रकारों की तुलना में कम रिसाव है जो स्पष्ट रूप से भरोसा करते हैं अंकन?

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

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

क्या यह मामला है कि उत्तरार्द्ध संसाधन विनाश के कार्यान्वयन का विवरण देता है, जबकि पूर्व में नहीं है?

संपादित करें: तुलना करें, मान लें कि रूबी से पर्ल अधिक निष्पक्ष हो सकते हैं क्योंकि एक में नियतात्मक विनाश होता है और दूसरा नहीं होता है, फिर भी वे दोनों कचरा एकत्र करते हैं।


5
मुझे "हां" कहने के लिए लुभाया जाता है, लेकिन मुझे यह सुनना पसंद है कि दूसरों को इस पर क्या कहना है।
बार्ट वैन इनगेन शेनॉ

पारदर्शी संसाधन विनाश? इस तथ्य के अलावा कि आपको सामान्य पॉइंटर्स के बजाय स्मार्ट पॉइंटर्स का उपयोग करना है? मुझे नहीं लगता कि वस्तुओं तक पहुंचने के लिए सिर्फ एक तंत्र (संदर्भ) होने से यह अधिक पारदर्शी है (सी ++ में आपके पास कम से कम चार या पांच हैं)।
जियोर्जियो

@ जियोर्जियो: "किसी वस्तु तक पहुंचने के तरीके" काफी अस्पष्ट है। क्या आपका मतलब पढ़ना या लिखना है? कास्ट / अस्थिर योग्यता? पॉइंटर्स वास्तव में "एक वस्तु तक पहुंचने का एक तरीका" नहीं हैं; किसी भी वस्तु में बहुत अधिक अभिव्यक्ति का परिणाम होता है और पॉइंटर को डीफ़्रैफ़िंस करना बस इतना विशेष नहीं है।
MSalters

1
@ जियोर्जियो: उस ओओपी अर्थ में, आप C ++ पॉइंटर को संदेश नहीं भेज सकते। आपको संदेश भेजने के लिए सूचक को (*ptr).Message()बराबर करने की आवश्यकता है या समकक्ष ptr->Message()। अनुमत अभिव्यक्तियों का एक अनंत सेट है, जैसा ((*ptr))->Messageकि समतुल्य भी है। लेकिन वे सभी को उबालते हैंexpressionIdentifyingAnObject.Message()
MSalters

1
बचाव के साथ आपको हलकों से बचने के बारे में सावधान रहने की आवश्यकता है। तो वह अमूर्त लीक के रूप में अच्छी तरह से, बस एक अलग तरीके से।
कोडइन्चोज

जवाबों:


2

आपका अपना उदाहरण प्रश्न का उत्तर देता है। पारदर्शी विनाश स्पष्ट विनाश की तुलना में स्पष्ट रूप से कम टपका हुआ है। यह लीक हो सकता है, लेकिन कम रिसाव वाला है।

स्पष्ट विनाश सभी नुकसानों के साथ सी में मॉलोक / मुक्त के अनुरूप है। हो सकता है कि इसे बनाने के लिए कुछ सिंटैक्टिक शुगर के साथ यह स्कोप आधारित हो।

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


2

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

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

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

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

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

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


0

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

C ++ बनाम अन्य के लिए, बहुत अंतर नहीं है। C ++ उन सभी वस्तुओं पर इंटरफ़ेस करता है। जब वे भाषा द्वारा आवश्यक होते हैं, तो अंश लीक नहीं हो सकते।


4
"यदि आप एक उपप्रकार बनाते हैं जिसे विशेष विनाश की आवश्यकता नहीं है" तो यह एलएसपी उल्लंघन नहीं है, क्योंकि नो-ऑप विनाश का एक विशेष विशेष मामला है। समस्या तब होती है जब आप विनाश की आवश्यकता को एक व्युत्पन्न वर्ग में जोड़ते हैं।
कोडइन्चौस

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

@CodesInChaos - आह हाँ, मुझे लगता है कि यह सच है।
तेलस्तीन

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

0

मेरा प्रश्न यह है: स्मार्ट पॉइंटर्स या रेफरेंस-काउंटिंग गारबेज कलेक्शन सिस्टम के लिए विध्वंसक - लगभग एक ही चीज है - निहित और पारदर्शी संसाधन विनाश की अनुमति दें, क्या यह गैर-नियतात्मक प्रकारों की तुलना में कम रिसाव है जो स्पष्ट रूप से भरोसा करते हैं अंकन?

हाथ से चक्र देखने के लिए न तो निहित है और न ही पारदर्शी है। एकमात्र अपवाद एक भाषा के साथ एक संदर्भ गिनती प्रणाली है जो डिजाइन द्वारा चक्रों को प्रतिबंधित करता है। एर्लैंग ऐसी प्रणाली का एक उदाहरण हो सकता है।

इसलिए दोनों लीक हो गए। मुख्य अंतर यह है कि सी + + में हर जगह विनाशकारी रिसाव होता है लेकिन IDispose.NET पर बहुत कम है।


1
स्पष्ट रूप से चक्रीय होने वाले डेटा संरचनाओं को छोड़कर, चक्रों को छोड़कर दुर्लभ और व्यावहारिक रूप से कभी नहीं होते हैं। मुख्य अंतर यह है कि C ++ में डिस्ट्रक्टर्स को हर जगह ठीक से हैंडल किया जाता है, लेकिन IDispose शायद ही कभी .NET में समस्या को हैंडल करता है।
डेडएमजी

"सिवाय चक्रों के अत्यधिक दुर्लभ हैं"। आधुनिक भाषाओं में? मैं उस परिकल्पना को चुनौती दूंगा।
जॉन हैरोप
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.