एक बेहतर संगोष्ठी कहानी रस्ट परियोजना के मुख्य लक्ष्यों में से एक है, इसलिए सुधार की उम्मीद की जानी चाहिए, बशर्ते हम अपने लक्ष्यों को प्राप्त करने के लिए परियोजना पर भरोसा करते हैं। पूर्ण अस्वीकरण: मेरे पास रुस्ट की एक उच्च राय है और इसमें निवेश किया गया है। अनुरोध के अनुसार, मैं मानों के निर्णयों से बचने और (IMHO) सुधारों के बजाय मतभेदों का वर्णन करने का प्रयास करूँगा ।
सुरक्षित और असुरक्षित जंग
"जंग" दो भाषाओं से बना है: एक जो आपको सिस्टम प्रोग्रामिंग के खतरों से अलग करने की बहुत कोशिश करता है, और इस तरह की किसी भी आकांक्षाओं के बिना अधिक शक्तिशाली है।
Unsafe Rust एक गंदी, क्रूर भाषा है जो C ++ की तरह बहुत कुछ महसूस करती है। यह आपको मनमाने ढंग से खतरनाक चीजें करने की अनुमति देता है, हार्डवेयर से बात करता है, (गलत-) मेमोरी को मैन्युअल रूप से प्रबंधित करता है, अपने आप को पैर में गोली मारता है, आदि यह सी और सी ++ की तरह बहुत है कि कार्यक्रम की शुद्धता अंततः आपके हाथों में है। और इसमें शामिल सभी अन्य प्रोग्रामर के हाथ। आप इस भाषा को कीवर्ड के साथ चुनते हैं unsafe
, और C और C ++ की तरह, एक ही स्थान पर एक गलती से पूरी परियोजना दुर्घटनाग्रस्त हो सकती है।
सेफ रस्ट "डिफ़ॉल्ट" है, रस्ट कोड का सबसे बड़ा विशाल हिस्सा सुरक्षित है, और यदि आपने unsafe
अपने कोड में कभी भी कीवर्ड का उल्लेख नहीं किया है , तो आप सुरक्षित भाषा कभी नहीं छोड़ते हैं। बाकी पोस्ट ज्यादातर उस भाषा के साथ ही चिंता करेंगे, क्योंकि unsafe
कोड किसी भी और सभी गारंटी को तोड़ सकता है जो सुरक्षित जंग आपको देने के लिए बहुत मेहनत करता है। दूसरी तरफ, unsafe
कोड बुराई नहीं है और समुदाय द्वारा ऐसा नहीं माना जाता है (हालांकि, यह आवश्यक नहीं है जब दृढ़ता से हतोत्साहित किया जाता है)।
यह खतरनाक है, हाँ, लेकिन यह भी महत्वपूर्ण है, क्योंकि यह उन अमूर्त तत्वों को बनाने की अनुमति देता है जो सुरक्षित कोड का उपयोग करता है। अच्छा असुरक्षित कोड दूसरों को इसका दुरुपयोग करने से रोकने के लिए प्रकार प्रणाली का उपयोग करता है, और इसलिए एक रस्ट प्रोग्राम में असुरक्षित कोड की उपस्थिति को सुरक्षित कोड को परेशान करने की आवश्यकता नहीं है। निम्नलिखित सभी अंतर मौजूद हैं क्योंकि Rust के प्रकार के सिस्टम में ऐसे उपकरण हैं जो C ++ के पास नहीं हैं, और क्योंकि असुरक्षित कोड जो कि संगामिति सार को लागू करता है, इन उपकरणों का प्रभावी ढंग से उपयोग करता है।
गैर-अंतर: साझा / परस्पर स्मृति
हालाँकि, मैसेज पासिंग पर बहुत जोर देता है और साझा मेमोरी को बहुत सख्ती से नियंत्रित करता है, यह साझा मेमोरी कंसिस्टेंसी को नियंत्रित नहीं करता है और स्पष्ट रूप से कॉमन एब्स्ट्रक्शन (लॉक्स, एटॉमिक ऑपरेशंस, कंडीशन वैरिएबल, कंसर्ट कलेक्शन) को सपोर्ट करता है।
इसके अलावा, सी ++ की तरह और कार्यात्मक भाषाओं के विपरीत, रस्ट वास्तव में पारंपरिक अनिवार्य डेटा संरचनाओं को पसंद करता है। मानक पुस्तकालय में कोई निरंतर / अपरिवर्तनीय लिंक सूची नहीं है। वहाँ है, std::collections::LinkedList
लेकिन यह std::list
C ++ में जैसा है और उसी कारण से हतोत्साहित किया गया है std::list
(कैश का बुरा उपयोग)।
हालाँकि, इस खंड के शीर्षक ("साझा / परिवर्तनशील स्मृति") के संदर्भ में, रस्ट के C ++ में एक अंतर है: यह दृढ़ता से प्रोत्साहित करता है कि स्मृति को "साझा XOR उत्परिवर्तित" किया जाए, अर्थात, स्मृति कभी भी साझा नहीं की जाती है और एक ही समय में परिवर्तनशील होती है। पहर। स्मृति को "अपने स्वयं के धागे की गोपनीयता" में पसंद करें, इसलिए बोलना है। C ++ के साथ इसका विरोध करें जहां साझा की जाने योग्य स्मृति डिफ़ॉल्ट विकल्प है और व्यापक रूप से उपयोग की जाती है।
जबकि साझा-एक्सोर-म्यूटेबल प्रतिमान नीचे के मतभेदों के लिए बहुत महत्वपूर्ण है, यह भी एक काफी अलग प्रोग्रामिंग प्रतिमान है जिसका उपयोग करने के लिए कुछ समय लगता है, और यह महत्वपूर्ण प्रतिबंध लगाता है। कभी-कभी किसी को इस प्रतिमान से बाहर निकलना पड़ता है, उदाहरण के लिए, परमाणु प्रकार के साथ ( AtomicUsize
साझा साझा स्मृति का सार है)। ध्यान दें कि ताले साझा-एक्सोर-म्यूटेबल नियम का भी पालन करते हैं, क्योंकि यह समवर्ती पढ़ता है और लिखता है (जबकि एक धागा लिखता है, कोई अन्य धागा पढ़ या लिख नहीं सकता है)।
गैर-अंतर: डेटा दौड़ अपरिभाषित व्यवहार (UB) हैं
यदि आप Rust कोड में डेटा रेस को ट्रिगर करते हैं, तो यह C ++ की तरह ही गेम ओवर है। सभी दांव बंद हैं और कंपाइलर जो चाहे उसे कर सकता है।
हालांकि, यह एक कठिन गारंटी है कि सुरक्षित रस्ट कोड में डेटा दौड़ (या उस मामले के लिए कोई यूबी) नहीं है। यह दोनों मूल भाषा और मानक पुस्तकालय तक फैली हुई है। यदि आप एक रस्ट प्रोग्राम लिख सकते हैं जो unsafe
(तीसरे पक्ष के पुस्तकालयों में लेकिन मानक पुस्तकालय को छोड़कर) का उपयोग नहीं करता है जो यूबी को ट्रिगर करता है, तो इसे बग माना जाता है और इसे ठीक किया जाएगा (यह पहले से ही कई बार हो चुका है)। अगर यह C ++ के विपरीत है, जहां यह UB के साथ प्रोग्राम लिखने के लिए मामूली है।
अंतर: सख्त ताला अनुशासन
C ++, जंग (में एक ताला std::sync::Mutex
, std::sync::RwLock
आदि) का मालिक डेटा यह रक्षा कर रहा है। ताला लेने के बजाय और फिर कुछ साझा की गई मेमोरी में हेरफेर करना जो केवल दस्तावेज़ में लॉक से जुड़ा है, साझा डेटा अप्राप्य है जबकि आप लॉक को पकड़ नहीं पाते हैं। एक RAII गार्ड लॉक रखता है और साथ ही साथ लॉक किए गए डेटा तक पहुंच देता है (यह C ++ द्वारा लागू किया जा सकता है, लेकिन std::
लॉक द्वारा नहीं )। जीवनकाल प्रणाली यह सुनिश्चित करती है कि लॉक जारी करने के बाद आप डेटा तक पहुँच नहीं रख सकते (RAII गार्ड को छोड़ दें)।
आप निश्चित रूप से एक ताला लगा सकते हैं जिसमें कोई उपयोगी डेटा नहीं है ( Mutex<()>
), और बस कुछ मेमोरी को स्पष्ट रूप से उस लॉक के साथ जोड़कर साझा करें। हालाँकि, संभावित असंबद्ध साझा मेमोरी की आवश्यकता होती है unsafe
।
अंतर: आकस्मिक बंटवारे की रोकथाम
यद्यपि आप साझा की गई स्मृति को साझा कर सकते हैं, आप केवल तभी साझा करते हैं जब आप स्पष्ट रूप से इसके लिए पूछते हैं। उदाहरण के लिए, जब आप संदेश पासिंग (जैसे चैनल से std::sync
) का उपयोग करते हैं, तो जीवनकाल प्रणाली यह सुनिश्चित करती है कि आप डेटा को किसी अन्य थ्रेड पर भेजने के बाद किसी भी संदर्भ को न रखें। एक लॉक के पीछे डेटा साझा करने के लिए, आप स्पष्ट रूप से लॉक का निर्माण करते हैं और इसे दूसरे धागे को देते हैं। आपके साथ असम्बद्ध मेमोरी साझा करने के लिए unsafe
, अच्छी तरह से, उपयोग करना होगा unsafe
।
यह अगले बिंदु में शामिल है:
अंतर: थ्रेड-सुरक्षा ट्रैकिंग
रस्ट प्रकार प्रणाली थ्रेड सुरक्षा की कुछ धारणा को ट्रैक करती है। विशेष रूप से, Sync
लक्षण उन प्रकारों को दर्शाता है जिन्हें डेटा थ्रेड्स के जोखिम के बिना कई थ्रेड्स द्वारा साझा किया जा सकता है, जबकि Send
उन लोगों को चिह्नित करता है जिन्हें एक धागे से दूसरे में स्थानांतरित किया जा सकता है। यह पूरे कार्यक्रम में कंपाइलर द्वारा लागू किया जाता है, और इस तरह पुस्तकालय डिजाइनर ऐसे अनुकूलन करते हैं जो इन स्थैतिक जांचों के बिना मूर्खतापूर्ण रूप से खतरनाक होंगे। उदाहरण के लिए, C ++ का std::shared_ptr
जो हमेशा परमाणु संदर्भों का उपयोग अपने संदर्भ संख्या में हेरफेर करने के लिए करता है, यूबी से बचने के लिए यदि shared_ptr
कई थ्रेड्स द्वारा उपयोग किया जाता है। जंग है Rc
और Arc
, जो केवल उस में अलग-अलग है जो Rc
गैर-परमाणु भाटा संचालन का उपयोग करता है और थ्रेडसेफ़ नहीं है (यानी लागू नहीं करता है Sync
या Send
) जबकि Arc
बहुत पसंद हैshared_ptr
(और दोनों लक्षण लागू करता है)।
ध्यान दें कि यदि कोई प्रकार मैन्युअल रूप से सिंक्रनाइज़ेशन को लागू करने के लिए उपयोग नहीं करता हैunsafe
, तो लक्षण की उपस्थिति या अनुपस्थिति को सही ढंग से अनुमान लगाया गया है।
अंतर: बहुत सख्त नियम
यदि कंपाइलर पूरी तरह से सुनिश्चित नहीं हो सकता है कि कुछ कोड डेटा रेस और अन्य यूबी से मुक्त है, तो यह संकलित नहीं होगा, अवधि । उपरोक्त नियम और अन्य उपकरण आपको काफी दूर तक पहुंचा सकते हैं, लेकिन जितनी जल्दी या बाद में आप कुछ ऐसा करना चाहते हैं जो सही है, लेकिन सूक्ष्म कारणों से जो संकलक के नोटिस से बच जाते हैं। यह एक पेचीदा लॉक-फ्री डेटा संरचना हो सकती है, लेकिन यह कुछ हद तक सांसारिक भी हो सकती है क्योंकि "मैं एक साझा सरणी में यादृच्छिक स्थानों पर लिखता हूं लेकिन सूचकांक ऐसे गणना किए जाते हैं कि हर स्थान केवल एक धागे से लिखा जाता है"।
उस बिंदु पर आप या तो बुलेट को काट सकते हैं और अनावश्यक सिंक्रनाइज़ेशन का एक सा जोड़ सकते हैं, या आप कोड को फिर से बनाते हैं ताकि कंपाइलर अपनी शुद्धता (अक्सर उल्लेखनीय, कभी-कभी काफी कठिन, कभी-कभी असंभव) देख सके, या आप unsafe
कोड में गिर जाते हैं । फिर भी, यह अतिरिक्त मानसिक ओवरहेड है, और रस्ट आपको unsafe
कोड की शुद्धता के लिए कोई गारंटी नहीं देता है ।
अंतर: कम उपकरण
उपरोक्त मतभेदों के कारण, जंग में यह बहुत अधिक दुर्लभ है कि एक कोड लिखता है जिसमें डेटा दौड़ हो सकती है (या मुफ्त के बाद उपयोग, या एक डबल मुक्त, या ...)। हालांकि यह अच्छा है, इसका दुर्भाग्यपूर्ण साइड इफेक्ट है कि इस तरह की त्रुटियों को ट्रैक करने के लिए पारिस्थितिकी तंत्र एक से अधिक अविकसित है जो कि युवाओं और समुदाय के छोटे आकार को देखते हुए उम्मीद करता है।
हालांकि वेलग्रिंड और एलएलवीएम के थ्रेड सैनिटाइजर जैसे उपकरण रूस्ट कोड पर लागू हो सकते हैं, क्या यह वास्तव में काम करता है, टूल से टूल में भिन्न होता है (और यहां तक कि काम करने के लिए सेट करना मुश्किल हो सकता है, खासकर जब से आपको कोई अप-अप नहीं मिल सकता है -उपाय कैसे करना है, इस पर संसाधन)। यह वास्तव में मदद नहीं करता है कि रस्ट वर्तमान में एक वास्तविक विनिर्देश और विशेष रूप से एक औपचारिक मेमोरी मॉडल की कमी है।
संक्षेप में, unsafe
Rust कोड को सही ढंग से लिखना C ++ कोड को सही तरीके से लिखने की तुलना में कठिन है, दोनों भाषाओं में क्षमता और जोखिम के मामले में लगभग तुलनीय होने के बावजूद। बेशक यह इस तथ्य के खिलाफ भारित किया जाना चाहिए कि एक ठेठ जंग कार्यक्रम में unsafe
कोड का केवल एक छोटा सा अंश होगा , जबकि एक C ++ प्रोग्राम अच्छी तरह से, पूरी तरह से C ++ है।