Rust को गार्बेज कलेक्टर की आवश्यकता क्यों नहीं है, फिर भी यह सुरक्षित है?
\n\nजब डेवलपर्स, जो Python, Java या C# के आदी हैं, पहली बार Rust के बारे में सुनते हैं, तो वे अक्सर परिचित गार्बेज कलेक्टर (GC) की अनुपस्थिति से डर जाते हैं। "यह कैसे हो सकता है? — वे सोचते हैं। — GC के बिना हम मैन्युअल मेमोरी प्रबंधन, मेमोरी लीक और segmentation fault के युग में वापस चले जाएंगे?"
\n\nस्पॉयलर: नहीं, हम वापस नहीं जाएंगे। Rust एक तीसरा रास्ता प्रस्तुत करता है — स्वामित्व (ownership) प्रणाली, जो संकलन चरण में मेमोरी सुरक्षा की गारंटी देती है। कोई रनटाइम नहीं, कोई GC नहीं, कोई डैंगलिंग पॉइंटर्स नहीं। केवल स्पष्ट नियम और एक कंपाइलर जो आपको अपने पैर में गोली मारने नहीं देगा।
\n\nइस लेख में, हम समझेंगे कि Rust में मेमोरी कैसे काम करती है, RAII, स्वामित्व, उधार और जीवनकाल क्या हैं, और यह सब Rust को सबसे विश्वसनीय सिस्टम प्रोग्रामिंग भाषाओं में से एक क्यों बनाता है।
\n\nRust में मेमोरी कैसे व्यवस्थित है: स्टैक और हीप
\n\nकिसी भी निम्न-स्तरीय भाषा की तरह, Rust में मेमोरी दो मुख्य क्षेत्रों में विभाजित होती है:
\n\n- \n
- स्टैक (stack) — तेज़, आकार में सीमित मेमोरी, जो LIFO सिद्धांत पर काम करती है। यहाँ स्थानीय चर, फ़ंक्शन तर्क और रिटर्न पते संग्रहीत होते हैं। \n
- हीप (heap) — धीमी लेकिन लचीली मेमोरी, जिसका उपयोग उन डेटा के लिए किया जाता है जिनका आकार संकलन चरण में ज्ञात नहीं होता (जैसे,
String,Vec,Box)। \n
C++ में, आप स्वयं तय करते हैं कि हीप को कब आवंटित और मुक्त करना है (new/delete के माध्यम से)। Java या Python में, गार्बेज कलेक्टर समय-समय पर प्रोग्राम को रोककर आपके लिए ऐसा करता है। Rust स्वामित्व प्रणाली का उपयोग करता है, जो चर के दायरे से बाहर होते ही स्वचालित रूप से मेमोरी मुक्त कर देता है।
उदाहरण: बुनियादी मेमोरी आवंटन
\n\nfn main() {\n let s = String::from("Привет, мир!"); // हीप में मेमोरी आवंटन\n println!("{}", s);\n} // यहाँ s दायरे से बाहर हो जाता है, मेमोरी मुक्त हो जाती है\n\nध्यान दें: कोई free() या delete नहीं है। ब्लॉक के अंत में, कंपाइलर अंतर्निहित रूप से डिस्ट्रक्टर — drop() डालता है। इसे RAII (Resource Acquisition Is Initialization) कहा जाता है — संसाधन आरंभीकरण पर प्राप्त किया जाता है और ऑब्जेक्ट के नष्ट होने पर मुक्त किया जाता है।
स्वामित्व (Ownership): Rust का मुख्य नियम
\n\nRust में स्वामित्व प्रणाली तीन सरल नियमों पर आधारित है:
\n\n- \n
- Rust में प्रत्येक मान का ठीक एक मालिक (owner) होता है। \n
- जब मालिक दायरे से बाहर होता है, तो मान हटा दिया जाता है। \n
- मालिक को स्थानांतरित (move) या अस्थायी रूप से उधार (borrow) दिया जा सकता है। \n
उबाऊ लगता है? आइए देखें कि यह व्यवहार में कैसे काम करता है।
\n\nस्थानांतरण (Move)
\n\nfn main() {\n let s1 = String::from("hello");\n let s2 = s1; // s1 को s2 में स्थानांतरित कर दिया गया\n // println!("{}", s1); // त्रुटि! s1 अब डेटा का मालिक नहीं है\n println!("{}", s2); // OK\n}\n\nC++ में, ऐसा असाइनमेंट एक ही मेमोरी पर दो पॉइंटर्स — और डबल फ्री की ओर ले जाएगा। Rust में, कंपाइलर स्थानांतरण के बाद s1 का उपयोग करने से मना कर देता है। कोई लीक नहीं, कोई डबल डिलीट नहीं।
कॉपी (Copy)
\n\nसरल प्रकार, जैसे पूर्णांक, बूलियन मान और वर्ण, Copy ट्रेट को लागू करते हैं। उनके लिए, असाइनमेंट एक पूर्ण प्रतिलिपि बनाता है:
fn main() {\n let x = 42;\n let y = x;\n println!("x = {}, y = {}", x, y); // दोनों उपलब्ध हैं!\n}\n\nऐसा क्यों? क्योंकि i32 स्टैक पर संग्रहीत होता है, और इसकी प्रतिलिपि बनाना केवल कुछ बाइट्स की प्रतिलिपि बनाना है। सस्ता और सुरक्षित।
उधार (Borrowing) और संदर्भ
\n\nक्या होगा यदि आपको स्वामित्व स्थानांतरित किए बिना अस्थायी रूप से डेटा तक पहुँच देनी हो? संदर्भों का उपयोग करें। Rust आपको संदर्भ द्वारा मान उधार लेने की अनुमति देता है।
\n\nfn main() {\n let s = String::from(