कूड़ा बीनने वाले के बजाय रस्ट के पास क्या है?


95

मैं समझता हूं कि रस्ट में कूड़ा उठाने वाला नहीं है और मैं सोच रहा हूं कि जब बंधन एक दायरे से बाहर हो जाता है तो मेमोरी कैसे मुक्त हो जाती है।

इसलिए इस उदाहरण में, मैं समझता हूं कि जब यह कार्यक्षेत्र से बाहर हो जाता है, तो रुस्त '' ए 'को आवंटित स्मृति को पुनः प्राप्त करता है।

{
    let a = 4
}

समस्या यह है कि मैं इसके साथ हूं, सबसे पहले यह कैसे होता है, और दूसरी बात यह नहीं है कि यह एक तरह का कचरा संग्रह है? यह 'विशिष्ट' कचरा संग्रह से कैसे भिन्न होता है?


12
"नियतात्मक वस्तु जीवनकाल"। C ++ के समान।
user2864740 8:20 बजे

@ user2864740 यह गाइड अच्छी तरह से पुराना है। आधुनिक प्रतिस्थापन शायद doc.rust-lang.org/book/references-and-borrowing.html होगा
विड्राक

जवाबों:


74

कचरा संग्रह आमतौर पर समय-समय पर या मांग पर उपयोग किया जाता है, जैसे कि ढेर कुछ दहलीज के पूर्ण या ऊपर है। यह तब अप्रयुक्त चर की तलाश करता है और एल्गोरिथ्म के आधार पर, उनकी मेमोरी को मुक्त करता है

जंग का पता तब चलता है जब चर दायरे से बाहर हो जाता है या इसका जीवनकाल संकलन के समय समाप्त हो जाता है और इस प्रकार मेमोरी को मुक्त करने के लिए संबंधित एलएलवीएम / विधानसभा निर्देश सम्मिलित करते हैं।

जंग भी कुछ प्रकार के कचरे के संग्रह की अनुमति देती है, जैसे कि परमाणु संदर्भ गणना


चर का परिचय देते समय मेमोरी को आवंटित करने और मेमोरी को खाली करने के बाद जब मेमोरी की आवश्यकता नहीं होती है? मैं वास्तव में नहीं जानता कि आप इसके साथ क्या कहना चाहते हैं। हो सकता है कि जीसी फिर क्या है, इस पर हमारी अलग राय हो।
अयोनिक्स

1
उनका सवाल यह है कि रस्ट का दृष्टिकोण एक विशिष्ट जीसी से कैसे भिन्न होता है। तो मैंने समझाया कि जीसी क्या है और आरसी के बिना जंग कैसे होती है।
अयोनिक्स

1
doc.rust-lang.org/book/the-stack-and-the-heap.html इसे बहुत अच्छी तरह से समझाता है। हां, बहुत सी चीजें स्टैक में हैं लेकिन अकेले पर्याप्त संकेतक नहीं हैं (बॉक्स देखें)। मैंने सादगी की खातिर उसे छोड़ दिया, क्योंकि सवाल आम तौर पर पूछ रहा था
अयोनिक्स

1
@Amomum असल में Rust में new()C की तरह कोई अभिषिक्त कार्य नहीं है, वे सिर्फ स्थैतिक कार्य हैं, और विशेष रूप से जैसे कुछ let x = MyStruct::new()स्टैक पर अपनी वस्तु बनाता है। असली ढेर आवंटन का सूचक है Box::new()(या संरचनाओं कि बॉक्स पर निर्भर के किसी भी)।
मारियो कार्नेइरो

1
रुस्ट के समान स्मृति प्रबंधन किन अन्य भाषाओं को संभालता है?
still_dreaming_1

43

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

कूड़े के संग्रह वाली भाषाएं समय-समय पर अप्रयुक्त वस्तुओं को खोजने के लिए मेमोरी (एक ही रास्ता या किसी अन्य) को स्कैन करती हैं, उनसे जुड़े संसाधनों को जारी करती हैं, और अंत में उन वस्तुओं द्वारा उपयोग की जाने वाली मेमोरी को छोड़ देती हैं।

जंग के पास जीसी नहीं है, यह कैसे प्रबंधन करता है?

जंग का स्वामित्व है। एक affine type सिस्टम का उपयोग करते हुए , यह ट्रैक करता है कि कौन सा वैरिएबल अभी भी एक ऑब्जेक्ट पर पकड़ रहा है और, जब ऐसा वैरिएबल स्कोप से बाहर चला जाता है, तो इसके डिस्ट्रक्टर को कॉल करता है। आप एफिन प्रकार की प्रणाली को बहुत आसानी से देख सकते हैं:

fn main() {
    let s: String = "Hello, World!".into();
    let t = s;
    println!("{}", s);
}

पैदावार:

<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4         println!("{}", s);

<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3         let t = s;
                     ^

जो पूरी तरह से दिखाता है कि भाषा के स्तर पर किसी भी समय, स्वामित्व को ट्रैक किया जाता है।

यह स्वामित्व पुनरावर्ती रूप से काम करता है: यदि आपके पास एक Vec<String>(यानी, तार का एक गतिशील सरणी) है, तो प्रत्येक Stringका स्वामित्व Vecस्वयं एक चर या किसी अन्य वस्तु, आदि के स्वामित्व में है ... इस प्रकार, जब एक चर दायरे से बाहर हो जाता है, यह अप्रत्यक्ष रूप से आयोजित सभी संसाधनों को पुन: जमा करता है। इस मामले में Vec<String>इसका मतलब है:

  1. प्रत्येक से जुड़ी मेमोरी बफर जारी करना String
  2. मेमोरी बफ़र को Vecस्वयं से संबंधित रिलीज़ करना

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

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


2
"गारबेज कलेक्टर के साथ भाषाएं समय-समय पर मेमोरी (एक ही रास्ता या किसी अन्य) को स्कैन करती हैं"। कई करते हैं, लेकिन सामान्य रूप से यह सच नहीं है। रियल-टाइम कचरा संग्रहकर्ता समय-समय पर बजाय नियमित रूप से स्कैन करते हैं। Mathematica जैसी संदर्भ गिनती भाषाएं बिल्कुल भी स्कैन नहीं करती हैं।
JD

@JonHarrop: मैं एक पूर्ण कचरा संग्रह तंत्र के रूप में संदर्भ-गिनती की गणना नहीं करता हूं क्योंकि इसे लीक चक्र से बचने के लिए पूरक होना चाहिए। वृद्धिशील / आवधिक अंतर के रूप में, यह अंग्रेजी की मेरी खराब कमांड हो सकती है, लेकिन मैं यह देखने में विफल रहता हूं कि आवधिक वृद्धिशील मामले को कवर नहीं करता है ... मुझे लगता है कि "(एक रास्ता या दूसरा)" बिट पर्याप्त रूप से कई विविधताओं को बताता है। दृष्टिकोण मौजूद हैं। किसी भी स्थिति में, यदि आपके पास कचरा संग्रह का वर्णन करने का एक बेहतर तरीका है, तो कृपया सुझाव दें। हालाँकि, मेरे पास पूर्ण-व्याख्या में खुद को लॉन्च करने का कोई इरादा नहीं है: मैं इसके लिए अयोग्य हूं।
मैथ्यू एम।

1
"मैं एक पूर्ण कचरा संग्रह तंत्र के रूप में संदर्भ-गिनती की गिनती नहीं करता हूं क्योंकि इसे लीक चक्र से बचने के लिए पूरक होना चाहिए"। RC को पारंपरिक रूप से GC के रूप में माना जाता है। उदाहरण के लिए, Mathematica और Erlang में, चक्रों को डिज़ाइन द्वारा नहीं बनाया जा सकता है, इसलिए RC लीक नहीं करता है। उच्च-स्तरीय परिप्रेक्ष्य के लिए, "कचरा संग्रह का एक एकीकृत सिद्धांत" देखें cs.virginia.edu/~cs415/reading/bacon-garbage.pdf
JD

@ जोनरोप: सच है, अगर कोई चक्र संभव नहीं है तो आरसी लीक नहीं हो सकता।
मथिउ एम।

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

6

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

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

अधिक जानकारी यहाँ उपलब्ध है: https://doc.rust-lang.org/book/the-stack-and-the-heap.html


3
यदि स्टैक का उपयोग करना आसान है, तो निर्धारक वस्तु जीवनकाल को तब भी नियंत्रित किया जा सकता है यदि सभी मान 'ढेर पर बनाए गए' हों। इस प्रकार यह एक कार्यान्वयन विवरण है; जरूरी नहीं कि भाषा की रणनीति हो।
user2864740 8:20 बजे

2
आप उस शब्द का इस्तेमाल जारी रखें। मुझे नहीं लगता कि इसका मतलब है कि आप क्या सोचते हैं इसका मतलब है।
स्विस

मतलब जो मैं व्यक्त करना चाहता हूं ; गैर-निर्धारक जीवनकाल के विपरीत होना। एक बेहतर वाक्यांश के लिए एक प्रस्ताव बनाएं।
user2864740 8:20 बजे

उत्तर के लिए धन्यवाद, मैंने पहले एक को अंक दिए हैं क्योंकि यह पहले प्रस्तुत किया गया था। जानकारी उतनी ही उपयोगी और मान्य है।
रिक्स

@ user2864740 निर्धारक वस्तु जीवन काल का तात्पर्य वास्तव में यह बताने में सक्षम होने से है कि जब वस्तु को नष्ट कर दिया गया है तो वस्तु की मेमोरी को साफ कर दिया जाएगा। इसका इससे कोई लेना-देना नहीं है कि विध्वंसक को पहले स्थान पर कैसे बुलाया जाता है। आप एक ही शब्द को बार-बार सामने लाते रहते हैं, भले ही प्रश्न का कोई सीधा महत्व न हो।
स्विस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.