यदि .NET में एक मेमोरीस्ट्रीम को बंद नहीं किया जाता है, तो क्या मेमोरी लीक बनाई जाती है?


112

मेरे पास निम्नलिखित कोड हैं:

MemoryStream foo(){
    MemoryStream ms = new MemoryStream();
    // write stuff to ms
    return ms;
}

void bar(){
    MemoryStream ms2 = foo();
    // do stuff with ms2
    return;
}

क्या कोई मौका है कि मैंने जो मेमोरीस्ट्रीम आवंटित किया है, वह किसी तरह बाद में निपटाने में विफल हो जाएगा?

मुझे एक सहकर्मी समीक्षा मिली है कि मैं इसे मैन्युअल रूप से बंद करता हूं, और मुझे यह बताने के लिए जानकारी नहीं मिल सकती है कि उसके पास एक वैध बिंदु है या नहीं।


41
अपने समीक्षक से पूछें कि वह क्यों सोचता है कि आपको इसे बंद कर देना चाहिए। अगर वह सामान्य अच्छे अभ्यास के बारे में बात करता है, तो वह शायद स्मार्ट हो रहा है। यदि वह पहले मेमोरी जारी करने की बात करता है, तो वह गलत है।
जॉन स्कीट

जवाबों:


60

यदि कुछ डिस्पोजेबल है, तो आपको हमेशा इसे डिस्पोज़ करना चाहिए। आपको usingअपने कथन का उपयोग करना चाहिएbar() यह सुनिश्चित करने के लिए तरीके से कि यह ms2विवादित है।

यह अंततः कचरा कलेक्टर द्वारा साफ हो जाएगा, लेकिन डिस्पोज को कॉल करना हमेशा अच्छा होता है। यदि आप अपने कोड पर FxCop चलाते हैं, तो यह इसे एक चेतावनी के रूप में चिह्नित करेगा।


16
ब्लॉकिंग कॉल आपके लिए डिस्पोजल है।
निक

20
@Grauenwolf: आपके दावे में अतिक्रमण है। एक उपभोक्ता के रूप में, आपको परवाह नहीं करनी चाहिए कि क्या यह नहीं है: यदि यह आईडीसिसोपाय है, तो यह आपका काम है डिस्पोज करना ()।
मार्क Gravell

4
यह स्ट्रीमराइटर वर्ग के लिए सही नहीं है: यह कनेक्टेड स्ट्रीम को तभी डिस्पोज़ करेगा जब आप स्ट्रीमविटर को डिस्पोज़ करेंगे - यह स्ट्रीम को कभी भी डिस्पोज़ नहीं करेगा यदि यह कचरा इकट्ठा हो जाता है और इसका फाइनल हो जाता है - यह डिज़ाइन द्वारा है।
वसंत ऋतु 76

4
मुझे पता है कि यह सवाल 2008 से था, लेकिन आज हमारे पास .NET 4.0 टास्क लाइब्रेरी है। कार्य का उपयोग करते समय अधिकांश मामलों में निपटान () अनावश्यक है । हालांकि मैं इस बात से सहमत होता हूं कि आईडीसोपायरी का मतलब यह होना चाहिए कि "जब आप काम पूरा कर लें तो इसका बेहतर निपटान करें," इसका मतलब यह नहीं है कि अब और नहीं।
फिल

7
एक अन्य उदाहरण है कि आपको आईडीसोपायरी ऑब्जेक्ट को डिस्पोज़ नहीं करना चाहिए, HttpClient aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong BCL से बस एक और उदाहरण है जहाँ आईडीसोफ़रेबल ऑब्जेक्ट है और आपको ज़रूरत नहीं है (या फिर आपको डिस्पोज़ नहीं करना चाहिए। यह। यह केवल यह याद रखना है कि आमतौर पर BCL में भी सामान्य नियम के कुछ अपवाद हैं;)
Mariusz Pawelski

166

आप कुछ भी लीक नहीं करेंगे - कम से कम वर्तमान कार्यान्वयन में।

कॉलिंग डिस्पोज़ किसी भी तेज़ी से मेमोरीस्ट्रीम द्वारा उपयोग की जाने वाली मेमोरी को साफ नहीं करेगा। यह होगा कॉल, जो या आपके लिए उपयोगी नहीं हो सकता के बाद पढ़ें / लिखें कॉल के लिए व्यवहार्य होने से अपनी स्ट्रीम बंद करो।

यदि आप पूरी तरह से आश्वस्त हैं कि आप कभी भी मेमोरीस्ट्रीम से दूसरे प्रकार की धारा में नहीं जाना चाहते हैं, तो यह आपको डिस्पोज न करने के लिए कोई नुकसान नहीं पहुंचाने वाला है। हालाँकि, यह आम तौर पर अच्छा अभ्यास होता है क्योंकि यदि आप कभी ऐसा करते हैं एक अलग स्ट्रीम का उपयोग करने के परिवर्तन हैं, तो आप हार्ड-टू-ढूंढ बग से काट नहीं करना चाहते हैं क्योंकि आपने जल्दी से आसान रास्ता चुना है। (दूसरी ओर, वहाँ YAGNI तर्क है ...)

वैसे भी ऐसा करने का दूसरा कारण यह है कि एक नया कार्यान्वयन उन संसाधनों को प्रस्तुत कर सकता है जिन्हें निपटान पर मुक्त किया जाएगा।


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

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

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

@ ट्रायनको वास्तव में सच नहीं है: विवरण के लिए देखें: stackoverflow.com/questions/574019/…
जॉर्ज स्टॉकर

10
YAGNI तर्क को दोनों तरीकों से लिया जा सकता है - क्योंकि किसी चीज को लागू न करने का निर्णय लेने के बाद से लागू IDisposableकरना एक विशेष मामला है जो सामान्य सर्वोत्तम-व्यवहार के खिलाफ चल रहा है, आप यह तर्क दे सकते हैं कि यह वह मामला है जो आपको तब तक नहीं करना चाहिए जब तक आपको वास्तव में YNNI के तहत ज़रूरत न हो सिद्धांत।
जॉन हन्ना

26

हाँ एक रिसाव है , आप कैसे LEAK को परिभाषित करते हैं और कितने LATER पर निर्भर करता है ...

यदि रिसाव से आपका मतलब है "स्मृति आवंटित की गई है, उपयोग के लिए अनुपलब्ध है, भले ही आप इसका उपयोग कर रहे हैं" और बाद में आप निपटान का आह्वान करने के बाद कभी भी मतलब रखते हैं, तो फिर हां एक रिसाव हो सकता है, हालांकि इसका स्थायी नहीं है (यानी के लिए आपके एप्लिकेशन रनटाइम का जीवन)।

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

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

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


6
मुझे यह प्रतिक्रिया पसंद है। कभी-कभी लोग उपयोग करने के दोहरे कर्तव्य को भूल जाते हैं: उत्सुक संसाधन पुनर्स्मरण और उत्सुक डेरेफेरिंग।
किट

1
दरअसल, हालांकि मैंने सुना है कि जावा के विपरीत, सी # संकलक "अंतिम संभावित उपयोग" का पता लगाता है, इसलिए यदि चर को अपने अंतिम संदर्भ के बाद दायरे से बाहर जाने के लिए किस्मत में है, तो यह सही अंतिम उपयोग के बाद कचरा संग्रह के लिए पात्र बन सकता है। , इससे पहले कि यह वास्तव में दायरे से बाहर हो जाए। देखें stackoverflow.com/questions/680550/explicit-nulling
Triynko

2
कचरा बीनने वाले और घबराने वाले इस तरह से काम नहीं करते हैं। स्कोप एक भाषा निर्माण है और ऐसा कुछ नहीं है जो रनटाइम का पालन करेगा। वास्तव में, आप संभवत: उस समय को याद कर रहे हैं जब ब्लॉक समाप्त होने पर कॉल को जोड़ें। देखें ericlippert.com/2015/05/18/...
पाब्लो Montilla

8

बुलाना .Dispose()(या साथ लपेटना)Using ) की आवश्यकता नहीं है।

आपके द्वारा कॉल किए जाने .Dispose()का कारण संसाधन को जल्द से जल्द जारी करना है

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


24
एक मेमोरीस्ट्रीम पर डिसपोजिंग कॉलिंग किसी भी मेमोरी को रिलीज नहीं करने वाली है। वास्तव में, आप अभी भी एक मेमोरीस्ट्रीम में डेटा पर प्राप्त कर सकते हैं, जिसे आपने डिस्पोजल कहा है - इसे आज़माएं :)
जॉन स्कीट

12
-1 जबकि यह एक मेमोरीस्ट्रीम के लिए सच है, सामान्य सलाह के रूप में यह सिर्फ गलत है। निपटान अप्रबंधित संसाधनों को जारी करने के लिए है , जैसे फ़ाइल हैंडल या डेटाबेस कनेक्शन। मेमोरी उस श्रेणी में नहीं आती है। आपको लगभग हमेशा मेमोरी खाली करने के लिए निर्धारित कचरा संग्रह के लिए इंतजार करना चाहिए।
जो

1
FileStreamवस्तुओं को आवंटित करने और निपटाने के लिए एक कोडिंग शैली को अपनाने का उल्टा क्या है और वस्तुओं के लिए एक अलग है MemoryStream?
रॉबर्ट रॉसनी

3
एक FileStream में अप्रबंधित संसाधन शामिल होते हैं जिन्हें वास्तव में Dispose कहने पर तुरंत मुक्त किया जा सकता है। दूसरी ओर एक मेमोरीस्ट्रीम, अपने _buffer वैरिएबल में एक प्रबंधित बाइट सरणी को संग्रहीत करता है, जिसे निपटान के समय मुक्त नहीं किया जाता है। वास्तव में, _buffer को मेमोरीस्ट्रीम के डिस्पोजल विधि में भी शून्य नहीं किया गया है, जो कि SHAMEFUL BUG IMO है क्योंकि संदर्भ को बंद करने से मेमोरी को जीसी राइट के निपटान के समय के लिए योग्य बनाया जा सकता है। इसके बजाय, एक lingering (लेकिन निपटारा) MemoryStream संदर्भ अभी भी स्मृति पर है। इसलिए, एक बार जब आप इसे निपटा लेते हैं, तो आपको इसे शून्य कर देना चाहिए अगर यह अभी भी दायरे में है।
त्रिकोको २५'१०

@ ट्रिएनोको - "इसलिए, एक बार जब आप इसे निपटाते हैं, तो आपको इसे भी अशक्त कर देना चाहिए अगर यह अभी भी गुंजाइश में है" - मैं असहमत हूं। यदि इसे कॉल करने के बाद फिर से उपयोग किया जाता है, तो यह NullReferenceException का कारण होगा। यदि डिस्पोज़ के बाद इसका फिर से उपयोग नहीं किया जाता है, तो इसे शून्य करने की कोई आवश्यकता नहीं है; जीसी काफी स्मार्ट है।
जो

8

यह पहले से ही उत्तर दिया गया है, लेकिन मैं सिर्फ इतना जोड़ूंगा कि सूचना को छिपाने का अच्छा पुराने जमाने का सिद्धांत है, जिसका मतलब है कि आप भविष्य के किसी बिंदु पर फिर से विचार करना चाहते हैं:

MemoryStream foo()
{    
    MemoryStream ms = new MemoryStream();    
    // write stuff to ms    
    return ms;
}

सेवा:

Stream foo()
{    
   ...
}

यह इस बात पर जोर देता है कि कॉल करने वालों को परवाह नहीं होनी चाहिए कि किस तरह की स्ट्रीम वापस आ रही है, और आंतरिक कार्यान्वयन को बदलना संभव बनाता है (उदाहरण के लिए जब यूनिट परीक्षण के लिए नकली)।

यदि आपने अपने बार कार्यान्वयन में निपटान का उपयोग नहीं किया है, तो आपको परेशानी होगी:

void bar()
{    
    using (Stream s = foo())
    {
        // do stuff with s
        return;
    }
}

5

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

जहाँ भी आप फू को कॉल करते हैं, आप (MemoryStream ms = foo ()) का उपयोग कर सकते हैं और मुझे लगता है कि आपको अभी भी ठीक होना चाहिए।


1
एक समस्या जो मैंने इस आदत के साथ निभाई है, वह यह है कि आप सुनिश्चित करें कि धारा का उपयोग कहीं और नहीं किया जा रहा है। उदाहरण के लिए मैंने एक JpegBitmapDecoder बनाया जो एक MemoryStream को इंगित करता है और फ्रेम्स लौटाया [0] (यह सोचकर कि यह डेटा को अपने आंतरिक स्टोर में कॉपी कर लेगा), लेकिन पाया गया कि बिटमैप केवल 20% समय ही दिखाएगा - यह पता चला क्योंकि मैं स्मृति धारा का निस्तारण कर रहा था।
devios1

यदि आपकी मेमोरी स्ट्रीम बनी रहना चाहिए (यानी एक ब्लॉकिंग का मतलब नहीं है), तो आपको डिस्पोज को कॉल करना चाहिए और तुरंत चर को शून्य करने के लिए सेट करना चाहिए। यदि आप इसका निपटान करते हैं, तो इसका उपयोग अब और नहीं किया जाता है, इसलिए आपको इसे तुरंत समाप्त करने के लिए भी सेट करना चाहिए। चाईग्यू एक संसाधन प्रबंधन मुद्दे जैसी आवाज़ों का वर्णन कर रहा है, क्योंकि आपको किसी चीज़ का संदर्भ नहीं सौंपना चाहिए, जब तक कि वह चीज़ जो आप उसे निपटाने के लिए ज़िम्मेदारी नहीं सौंप रहे हैं, और संदर्भ सौंपने वाली चीज़ जानता है कि यह अब इसके लिए ज़िम्मेदार नहीं है। ऐसा करने से।
त्रिकोको २५'१०

2

आप मेमोरी को लीक नहीं करेंगे, लेकिन आपका कोड समीक्षक आपको अपनी स्ट्रीम बंद करने का संकेत देने के लिए सही है। ऐसा करना विनम्र है।

एकमात्र ऐसी स्थिति जिसमें आप मेमोरी को लीक कर सकते हैं, जब आप गलती से स्ट्रीम का संदर्भ छोड़ देते हैं और इसे कभी बंद नहीं करते हैं। आप अभी भी वास्तव में मेमोरी लीक नहीं कर रहे हैं , लेकिन आप अनावश्यक रूप से उस समय की मात्रा बढ़ा रहे हैं जो आप इसका उपयोग करने का दावा करते हैं।


1
> आप अभी भी वास्तव में मेमोरी लीक नहीं कर रहे हैं, लेकिन आप अनावश्यक रूप से उस समय की मात्रा बढ़ा रहे हैं जो आप इसका उपयोग करने का दावा करते हैं। क्या आपको यकीन है? डिस्पोज़ मेमोरी को रिलीज़ नहीं करता है और इसे फ़ंक्शन में देर से कॉल करना वास्तव में उस समय का विस्तार कर सकता है जो इसे एकत्र नहीं किया जा सकता है।
जोनाथन एलन

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

2

मैं मुख्य रूप से स्थिरता के लिए bar()एक usingबयान में मेमोरीस्ट्रीम लपेटने की सलाह दूंगा :

  • अभी मेमोरीस्ट्रीम पर मेमोरी फ्री नहीं है .Dispose() , लेकिन यह संभव है कि भविष्य में कुछ बिंदु पर, या आप (या आपकी कंपनी में कोई और) इसे अपने स्वयं के कस्टम मेमोरीस्ट्रीम के साथ प्रतिस्थापित कर सकता है जो करता है, आदि।
  • यह आपके प्रोजेक्ट में एक पैटर्न स्थापित करने में मदद करता है ताकि यह सुनिश्चित हो सके कि सभी धाराएँ निपट गई हैं - यह कहते हुए कि "सभी धाराओं का निपटान किया जाना चाहिए" को और अधिक मजबूती से खींचा जाना चाहिए, इसके बजाय "कुछ धाराओं का निपटान किया जाना चाहिए, लेकिन कुछ को" नहीं करना है। ...
  • यदि आप कभी भी अन्य प्रकार की स्ट्रीम को वापस करने की अनुमति देने के लिए कोड बदलते हैं, तो आपको इसे वैसे भी निपटाने के लिए बदलना होगा।

एक अन्य चीज जो मैं आमतौर पर मामलों में करता हूं जैसे foo()कि एक आईडीसिसोप्लॉई बनाते और वापस करते समय यह सुनिश्चित करना है कि ऑब्जेक्ट के निर्माण के बीच कोई भी विफलता और returnअपवाद द्वारा पकड़ा गया है, ऑब्जेक्ट को डिस्पोज करता है, और अपवाद को फिर से फेंकता है:

MemoryStream x = new MemoryStream();
try
{
    // ... other code goes here ...
    return x;
}
catch
{
    // "other code" failed, dispose the stream before throwing out the Exception
    x.Dispose();
    throw;
}

1

यदि कोई ऑब्जेक्ट IDis प्रयोज्य को लागू करता है, तो आपको कॉल किया जाना चाहिए।

कुछ वस्तुओं में, डिस्पोज़ का मतलब होता है क्लोज़ और इसके विपरीत, उस मामले में, या तो अच्छा है।

अब, आपके विशेष प्रश्न के लिए, नहीं, आप मेमोरी को लीक नहीं करेंगे।


3
"मस्ट" एक बहुत ही मजबूत शब्द है। जब भी नियम होते हैं, तो उन्हें तोड़ने के परिणाम जानने के लायक है। मेमोरीस्ट्रीम के लिए, बहुत कम परिणाम हैं।
जॉन स्कीट

-1

मैं कोई .net विशेषज्ञ नहीं हूँ, लेकिन शायद यहाँ समस्या संसाधन है, अर्थात् फ़ाइल हैंडल, और मेमोरी नहीं। मुझे लगता है कि कचरा कलेक्टर अंततः स्ट्रीम को मुक्त कर देगा, और हैंडल को बंद कर देगा, लेकिन मुझे लगता है कि यह हमेशा स्पष्ट रूप से बंद करने के लिए सबसे अच्छा अभ्यास होगा, यह सुनिश्चित करने के लिए कि आप डिस्क पर सामग्री को फ्लश करते हैं।


एक मेमोरीस्ट्रीम सभी इन-मेमोरी है - यहां कोई फाइल हैंडल नहीं है।
जॉन स्कीट

-2

कचरा संग्रहित भाषाओं में अप्रबंधित संसाधनों का निपटान गैर-नियतात्मक है। यहां तक ​​कि अगर आप स्पष्ट रूप से डिस्पोज़ कहते हैं, तो आपके पास वास्तव में कोई नियंत्रण नहीं है जब बैकिंग मेमोरी वास्तव में मुक्त हो जाती है। निपटान को स्पष्ट रूप से कहा जाता है जब कोई वस्तु दायरे से बाहर जाती है, चाहे वह एक उपयोग कथन से बाहर निकलना हो, या कॉलस्टैक को अधीनस्थ विधि से पॉप अप करना हो। यह सब कहा जा रहा है, कभी-कभी ऑब्जेक्ट वास्तव में एक प्रबंधित संसाधन (जैसे फ़ाइल) के लिए एक आवरण हो सकता है। यही कारण है कि अंत में बयानों में स्पष्ट रूप से बंद करने या उपयोग कथन का उपयोग करने के लिए यह अच्छा अभ्यास है। चियर्स


1
बिल्कुल सच नहीं है। उपयोग कथन से बाहर निकलने पर डिस्पोज को कहा जाता है। निपटान को तब नहीं कहा जाता है जब कोई वस्तु बस दायरे से बाहर जाती है।
अलेक्जेंडर अब्रामोव

-3

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


6
-1: यदि आप स्वीकृत उत्तर के साथ 4+ वर्ष पुराने प्रश्न को पोस्ट करने जा रहे हैं, तो कृपया इसे कुछ उपयोगी बनाने का प्रयास करें।
टायसन टी।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.