.Net पुस्तकें स्टैक बनाम हीप मेमोरी आवंटन के बारे में बात क्यों करती हैं?


36

ऐसा लगता है कि प्रत्येक .net पुस्तक मान प्रकार बनाम संदर्भ प्रकारों के बारे में बात करती है और इसे एक बिंदु (अक्सर गलत तरीके से) स्थिति बनाती है जहां प्रत्येक प्रकार संग्रहीत किया जाता है - ढेर या स्टैक। आमतौर पर यह पहले कुछ अध्यायों में है और कुछ महत्वपूर्ण तथ्यों के रूप में प्रस्तुत किया गया है। मुझे लगता है कि यह प्रमाणन परीक्षाओं में भी शामिल है । स्टैक बनाम हीप को (शुरुआती) .Net डेवलपर्स के लिए भी क्यों मायने रखता है? आप सामान आवंटित करते हैं और यह सिर्फ काम करता है, है ना?


11
कुछ लेखकों ने अभी बहुत बुरा निर्णय लिया है कि शुरुआती लोगों को पढ़ाना क्या महत्वपूर्ण है और अप्रासंगिक शोर क्या है। हाल ही में देखी गई एक किताब में, एक्सेस मॉडिफायर के पहले उल्लेख में पहले से ही संरक्षित आंतरिक शामिल था , जिसे मैंने 6 साल के C # ... में कभी इस्तेमाल नहीं किया है ...
तिमवी ४'१

1
मेरा अनुमान है कि जिसने भी उस भाग के लिए मूल .Net प्रलेखन लिखा था, उसने इसका एक बड़ा सौदा किया, और यह दस्तावेज है कि लेखक मूल रूप से अपनी पुस्तकों पर आधारित हैं, और फिर यह बस के आसपास रहा।
ग्रेग

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

साक्षात्कार कार्गो पंथ?
डेन

जवाबों:


37

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

जैसा कि फेडे ने बताया, एरिक लिपर्ट के पास इस बारे में कहने के लिए कुछ बहुत दिलचस्प बातें हैं: http://blogs.msdn.com/b/ericlippert/archive/2010/09/30/the-truth-about-value-types.aspx

उस जानकारी के प्रकाश में, आप मूल रूप से पढ़ने के लिए मेरे पहले पैराग्राफ को समायोजित कर सकते हैं: "जिस कारण से लोग इस जानकारी को शामिल करते हैं और यह मानते हैं कि अतीत में इस ज्ञान की आवश्यकता के साथ गलत या अधूरी जानकारी के कारण यह महत्वपूर्ण है।"

उन लोगों के लिए जो यह सोचते हैं कि प्रदर्शन के कारणों के लिए यह अभी भी महत्वपूर्ण है: यदि आप चीजों को मापते हैं और पता लगाते हैं कि आप ढेर से स्टैक तक ले जाने के लिए क्या कार्रवाई करेंगे? अधिक संभावना है, आपको समस्या क्षेत्र के प्रदर्शन को बेहतर बनाने का एक अलग तरीका मिलेगा।


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

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

36

ऐसा लगता है कि प्रत्येक .NET बुक मान प्रकार बनाम संदर्भ प्रकारों के बारे में बात करती है और इसे एक बिंदु (अक्सर गलत तरीके से) स्थिति बनाती है जहां प्रत्येक प्रकार संग्रहीत किया जाता है - ढेर या स्टैक। आमतौर पर यह पहले कुछ अध्यायों में है और कुछ महत्वपूर्ण तथ्यों के रूप में प्रस्तुत किया गया है।

मैं पूरी तरह से सहमत हूँ; मैं इसे हमेशा देखता हूं।

क्यों .NET किताबें ढेर बनाम ढेर स्मृति आवंटन के बारे में बात करते हैं?

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

अब, उन नियमों को जानना और सी में उनका पालन करने की आवश्यकता नहीं है कि आप "ढेर" और "स्टैक" को समझते हैं। लेकिन अगर आप समझते हैं कि डेटा संरचनाएं कैसे काम करती हैं तो नियमों को समझना और उनका पालन करना अक्सर आसान होता है।

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

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

.NET डेवलपर्स के लिए भी स्टैक बनाम हीप क्यों मायने रखता है?

मेरी राय में, यह नहीं है। यह समझने के लिए बहुत महत्वपूर्ण है कि सामान क्या है:

  • एक संदर्भ प्रकार और एक मूल्य प्रकार के बीच कॉपी शब्दार्थ में क्या अंतर है?
  • "रेफरी इंट एक्स" पैरामीटर कैसे व्यवहार करता है?
  • मूल्य प्रकार अपरिवर्तनीय क्यों होना चाहिए?

और इसी तरह।

आप सामान आवंटित करते हैं और यह सिर्फ काम करता है, है ना?

यही आदर्श है।

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

इसी तरह, यथार्थवादी इंटरोप परिदृश्य हैं जिसमें यह जानना आवश्यक है कि ढेर पर क्या है और ढेर पर क्या है, और कचरा कलेक्टर क्या चारों ओर घूम सकता है। यही कारण है कि C # में "फिक्स्ड", "स्टैकलॉक" जैसी विशेषताएं हैं।

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


2
उत्तर के लिए धन्यवाद एरिक। इस विषय पर आपके हाल के ब्लॉग पोस्ट वास्तव में मुझे सवाल पोस्ट करने के लिए प्रेरित करते हैं।
ग्रेग

13

आप लोग सभी बिंदु को याद कर रहे हैं। स्कोप / हीप डिस्टिंक्शन महत्वपूर्ण है इसका कारण स्कोप है

struct S { ... }

void f() {
    var x = new S();
    ...
 }

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

class C { ... }

void f() {
     var x = new C();
     ...
}

पूरी तरह से अलग कहानी! चूँकि x अब ढेर पर है, x के दायरे से बाहर जाने के बाद इसका ऑब्जेक्ट (यानी, ऑब्जेक्ट ही , इसकी कॉपी नहीं) बहुत अच्छी तरह से जारी रह सकता है । वास्तव में, यह जीने का एकमात्र तरीका नहीं होगा यदि x इसका एकमात्र संदर्भ है। यदि "..." भाग में असाइनमेंट या मेथड कॉल ने अन्य सन्दर्भ बनाए हैं जो अभी भी x के दायरे से बाहर हैं, तब भी "लाइव" रहते हैं , तो वह वस्तु जीवित रहेगी।

यह एक बहुत ही महत्वपूर्ण अवधारणा है, और वास्तव में "क्या और क्यों" समझने का एकमात्र तरीका स्टैक और हीप आवंटन के बीच अंतर को जानना है।


मुझे यकीन नहीं है कि मैंने उस तर्क को किताबों में स्टैक / हीप चर्चा के साथ प्रस्तुत किया है, लेकिन यह अच्छा है। +1
ग्रेग

2
सी # जिस तरह से क्लोजर उत्पन्न करता है, ...उसके कारण कोड xको एक कंपाइलर-जनरेट किए गए वर्ग के एक क्षेत्र में परिवर्तित किया जा सकता है , और इस तरह संकेतित क्षेत्र को बाहर कर सकता है। व्यक्तिगत रूप से, मुझे निहित उत्थापन के विचार में अरुचिकर लगता है, लेकिन भाषा डिजाइनर इसके लिए जाने लगते हैं (जैसा कि आवश्यक है कि किसी भी चर को फहराए जाने के विरोध में इसकी घोषणा करने के लिए कुछ है)। कार्यक्रम की शुद्धता सुनिश्चित करने के लिए, किसी संदर्भ में मौजूद सभी संदर्भों के लिए अक्सर यह आवश्यक है। यह जानते हुए कि एक नियमित रिटर्न आने तक, एक पारित संदर्भ की कोई प्रति उपयोगी नहीं रहेगी।
सुपरकैट

1
जैसे कि 'स्ट्रक्चर्स स्टैक पर हैं', उचित कथन यह है कि यदि स्टोरेज लोकेशन घोषित किया जाता है structType foo, तो स्टोरेज लोकेशन fooउसके फील्ड की सामग्री को रखती है; यदि fooस्टैक पर है, तो इसके क्षेत्र हैं। अगर fooढेर पर है, तो उसके खेत हैं। यदि fooएक नेटवर्क Apple II में है, तो उसके क्षेत्र हैं। इसके विपरीत, अगर fooएक वर्ग प्रकार थे, यह या तो पकड़ होगा null, या एक संदर्भ किसी ऑब्जेक्ट को। केवल एक ही स्थिति जिसमें वर्ग-प्रकार के बारे में fooकहा जा सकता है कि वस्तु के क्षेत्र पकड़ेंगे यदि यह एक वर्ग का एकमात्र क्षेत्र है, और अपने आप को एक संदर्भ रखता है।
सुपरकैट

+1, मुझे आपकी अंतर्दृष्टि से प्यार है और मुझे लगता है कि यह मान्य है ... हालाँकि, मुझे नहीं लगता कि यह इस बात का औचित्य है कि क्यों किताबें इस विषय को इतनी गहराई से कवर करती हैं। ऐसा लगता है कि आपने यहां जो बताया, वह उक्त पुस्तक के उन 3 या 4 अध्यायों को प्रतिस्थापित कर सकता है और वे अधिक सहायक हो सकते हैं।
फ्रैंक वी।

1
मैं जो जानता हूं, उससे न तो ढांचा बनता है और न ही वे वास्तव में हमेशा ढेर बने रहते हैं।
सारा

5

जैसा कि वे विषय को कवर करते हैं, मैं @Kirk से सहमत हूं कि यह एक महत्वपूर्ण अवधारणा है, जिसे आपको समझना होगा। जितनी अच्छी तरह से आप तंत्र को जानते हैं, उतना ही बेहतर है कि आप महान अनुप्रयोगों को आसानी से कर सकें।

अब एरिक लिपर्ट आपसे सहमत हैं लगता है कि विषय अधिकांश लेखकों द्वारा सही ढंग से कवर नहीं किया गया है। मैं आपको हुड के नीचे क्या है की एक बड़ी समझ हासिल करने के लिए उसके ब्लॉग को पढ़ने की सलाह देता हूं।


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

5

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

मैं .NET के बारे में ज्यादा नहीं जानता, लेकिन जहां तक ​​मुझे पता है, निष्पादन से पहले इसका JITted है। उदाहरण के लिए JIT विश्लेषण से बच सकता है और क्या नहीं और अचानक आप सभी वस्तुओं को स्टैक पर या केवल कुछ रजिस्टरों में पड़े हुए हैं। आप यह नहीं जान सकते।

मुझे लगता है कि कुछ किताबें इसे केवल इसलिए कवर करती हैं क्योंकि लेखक इसके लिए बहुत महत्व रखते हैं, या क्योंकि वे मानते हैं कि उनके दर्शक ऐसा करते हैं (जैसे कि अगर आपने C ++ प्रोग्रामर के लिए "C # लिखा है" तो आपको शायद विषय को कवर करना चाहिए)।

बहरहाल, मुझे लगता है कि "स्मृति प्रबंधित है" की तुलना में कहने के लिए बहुत कुछ नहीं है। अन्यथा लोग गलत निष्कर्ष निकाल सकते हैं।


2

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


2
प्रबंधित भाषाओं में, आपको एक मान प्रकार और एक संदर्भ प्रकार के बीच का अंतर जानना होगा, लेकिन इससे आगे, यह धुरी के नीचे कैसे प्रबंधित किया जाता है, इसके बारे में धुरी सोच के चारों ओर लपेटना आसान है। यहाँ एक उदाहरण के लिए देखें: stackoverflow.com/questions/4083981/…
रॉबर्ट हार्वे

मुझे रॉबर्ट से सहमत होना चाहिए

आबंटित और स्टैक आवंटित के बीच का अंतर वही है जो मूल्य और संदर्भ प्रकारों के बीच का अंतर बताता है।
जेरेमी

3
@ जेरेमी: वास्तव में नहीं। ब्लॉगs.msdn.com/b/ericlippert/archive/2010/09/30/… पर
रॉबर्ट हार्वे

1
जेरेमी, हीप और स्टैक आवंटन के बीच का अंतर मूल्य प्रकार और संदर्भ प्रकारों के बीच के अलग-अलग व्यवहार को स्पष्ट नहीं कर सकता है , क्योंकि ऐसे समय होते हैं जब मूल्य प्रकार और संदर्भ प्रकार दोनों ढेर पर होते हैं, और फिर भी वे अलग तरह से व्यवहार करते हैं। समझने के लिए अधिक महत्वपूर्ण बात यह है (उदाहरण के लिए) जब आपको संदर्भ प्रकार बनाम मान प्रकारों के लिए पास-बाय-संदर्भ का उपयोग करने की आवश्यकता होती है। यह सिर्फ "यह एक मान प्रकार या संदर्भ प्रकार है" पर निर्भर करता है, न कि "यह ढेर पर है"।
टिम गुडमैन

2

कुछ किनारे मामले हो सकते हैं जहां यह अंतर कर सकता है। डिफ़ॉल्ट स्टैक स्पेस 1meg है जबकि ढेर कई टमटम है। इसलिए यदि आप समाधान को एक बड़ी संख्या में रखते हैं, तो ढेर का स्थान होने पर आप स्टैक स्पेस से बाहर निकल सकते हैं।

हालांकि, अधिकांश भाग के लिए यह काफी अकादमिक है।


हां, लेकिन मुझे संदेह है कि इनमें से कोई भी पुस्तक यह बताने के लिए दर्द उठाती है कि संदर्भ स्वयं स्टैक पर संग्रहीत हैं - इसलिए इससे कोई फर्क नहीं पड़ता कि आपके पास बहुत सारे संदर्भ प्रकार हैं या बहुत सारे प्रकार के मूल्य अभी भी आपके पास स्टैक ओवरफ्लो हो सकते हैं।
जेरेमी

0

जैसा कि आप कहते हैं, C # को स्मृति प्रबंधन को अलग करने के लिए माना जाता है, और ढेर बनाम ढेर आवंटन कार्यान्वयन विवरण हैं जो सिद्धांत में डेवलपर के बारे में जानने की आवश्यकता नहीं होनी चाहिए।

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

ध्यान दें कि Python या JavaScript के बारे में पुस्तकें यह नहीं बताती हैं कि यदि वे इसका उल्लेख भी करते हैं तो इससे कोई बड़ी बात नहीं होती। इसका कारण यह है कि सब कुछ या तो ढेर आवंटित या अपरिवर्तनीय है, जिसका अर्थ है कि अलग-अलग नकल करने वाले शब्दार्थ कभी भी खेल में नहीं आते हैं। उन भाषाओं में स्मृति का अमूर्त काम करता है, सी # में यह टपका हुआ है।

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