सवाल .NET मेमोरी लीक क्यों नहीं हो सकता है?


असुरक्षित कोड को अनदेखा करते हुए, .NET में स्मृति रिसाव नहीं हो सकता है। मैंने इसे कई विशेषज्ञों से अंतहीन पढ़ा है और मुझे विश्वास है। हालांकि, मुझे समझ में नहीं आता कि ऐसा क्यों है।

यह मेरी समझ है कि फ्रेमवर्क स्वयं सी ++ में लिखा गया है और सी ++ मेमोरी लीक के लिए अतिसंवेदनशील है।

  • क्या अंतर्निहित ढांचा इतना अच्छी तरह लिखित है, कि इसमें आंतरिक मेमोरी लीक की कोई संभावना नहीं है?
  • क्या ढांचे के कोड में कुछ ऐसा है जो आत्म-प्रबंधन करता है और यहां तक ​​कि स्वयं को ठीक करता है-मेमोरी लीक होगा?
  • क्या उत्तर कुछ और है जिसे मैंने नहीं माना है?

57
2018-03-26 19:17


मूल


कृपया किसी भी "विशेषज्ञ" को एक लिंक पोस्ट करें जिसमें कहा गया है कि .NET ढांचे (या कोई में ढांचा कोई भाषा) मेमोरी लीक करने के लिए। मुझे उस व्यक्ति को एक ई-मेल लिखना होगा। - Shaggy Frog
@ शगी मेंढक: नीचे जवाब देखें। ऐसा नहीं है कि .NET Framework दोषपूर्ण है या रिसाव नहीं कर सकता है। प्रश्न का उत्तर क्लासिक मेमोरी आवंटन / डीलोकेशन के बीच भेद पर निर्भर करता है अंदर फ्रेमवर्क के स्रोत कोड बनाम स्मृति प्रबंधन बनाम द्वारा संदर्भों को सौंपने के संबंध में ढांचा। यह शायद सारांश का बहुत सरल है, लेकिन नीचे कई अद्भुत और अधिक पूर्ण स्पष्टीकरण हैं। - Dinah
मैं केवल आपका प्रश्न पढ़ रहा हूं क्योंकि वर्तमान में यह कहा गया है: "असुरक्षित कोड को अनदेखा करते हुए, .NET में स्मृति रिसाव नहीं हो सकता है। मैंने इसे कई विशेषज्ञों से अंतहीन रूप से पढ़ा है और मुझे विश्वास है।" फ्रेमवर्क में बग होती है जो तय होती है, यही कारण है कि अपडेट हो जाता है। दोबारा, मैं कहूंगा कि मुझे इनमें से कुछ "विशेषज्ञ" राय पढ़ने में दिलचस्पी है, इसलिए कृपया इस तरह के लिंक पोस्ट करें। - Shaggy Frog


जवाब:


यहां पहले से ही कुछ अच्छे उत्तर हैं, लेकिन मैं एक अतिरिक्त बिंदु को संबोधित करना चाहता हूं। आइए अपने विशिष्ट प्रश्न पर फिर से ध्यान से देखें:


यह मेरी समझ है कि फ्रेमवर्क स्वयं सी ++ में लिखा गया है और सी ++ मेमोरी लीक के लिए अतिसंवेदनशील है।

  • क्या अंतर्निहित ढांचा इतना अच्छी तरह लिखित है, कि इसमें आंतरिक मेमोरी लीक की कोई संभावना नहीं है?
  • क्या ढांचे के कोड में कुछ ऐसा है जो आत्म-प्रबंधन करता है और यहां तक ​​कि स्वयं को ठीक करता है-मेमोरी लीक होगा?
  • क्या उत्तर कुछ और है जिसे मैंने नहीं माना है?

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

आप उलझन में हैं क्योंकि आप सही ढंग से समझते हैं कि यह वही बात नहीं है जैसा कि आपके द्वारा बनाए गए किसी भी प्रोग्राम में पारंपरिक मेमोरी रिसाव नहीं हो सकता है। अभी भी एक बग हो सकता है जो अपने कोड जो स्मृति को रिसाव करता है।

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

इसलिए यहां सही जवाब यह है कि यह आपके पहले सुझाव का एक रूप है:

क्या अंतर्निहित ढांचा इतना अच्छी तरह लिखित है, कि इसमें आंतरिक मेमोरी लीक की कोई संभावना नहीं है?

ऐसा नहीं है कि कोई संभावना नहीं है, लेकिन यह स्वयं को प्रबंधित करने से कहीं अधिक सुरक्षित है। मुझे निश्चित रूप से किसी के बारे में पता नहीं है जानने वाला ढांचे में रिसाव।


43
2018-03-27 03:27



एरिक लिपर्ट को इस पूरे प्रश्न को पढ़ना चाहिए (यहां एक वैनिटी सर्च जीत की उम्मीद है)। - Joel Coehoorn
बस इसमें जोड़ने के लिए: जो अपने कोड में वास्तव में मेमोरी लीक है (डब्ल्यूपीएफ में कुछ लीक हैं, एक उदाहरण: connect.microsoft.com/VisualStudio/feedback/details/529736/...)। बैश करने की कोशिश नहीं कर रहा है (मुझे .NET पसंद है :)), बस एक उदाहरण देने के लिए। - Michael Stum♦
@ माइकल: ठीक है वहाँ है जो अपने कोड और फिर वहाँ है जो अपने कोड। डब्ल्यूपीएफ प्रोग्रेसबार जैसी चीजें हैं और जैसी चीजें हैं String प्रकार। डब्ल्यूपीएफ प्रोग्रेसबार में अजीब बग या दो को शामिल करने का अधिक मौका है हमारी कोड, हालांकि आधार .NET कोड जिस पर हम सभी भरोसा करते हैं ( उन्हें तथा हमें ) ऐसी बग होने की संभावना कम है। - AnthonyWJones
धन्यवाद। आपने मेरे कोड बनाम उनके कोड के भेद को बनाकर अपना भ्रम साफ़ कर दिया। यदि, जब मैं अपना प्रबंधित कोड चलाता हूं, तो स्मृति का सबूत होता है और मुझे लगता है कि रिसाव फ्रेमवर्क के एक दोषपूर्ण हिस्से में हो रहा है, तो मेरा कोड अभी भी लीक नहीं माना जाता है। यह फ्रेमवर्क है जो लीक हो रहा है। यदि मेरा कोड फ्रेमवर्क के गैर-दोषपूर्ण संस्करण पर चलाना था, तो कोई रिसाव नहीं होगा। इसलिए, यहां तक ​​कि एक स्मृति रिसाव के साथ भी, मेरे प्रबंधित कोड में अभी भी स्मृति रिसाव नहीं है। वह विरोधाभास था जिसे मैं पहले मेल नहीं कर सका। - Dinah


नेट कर सकते हैं मेमोरी लीक है।

अधिकतर, लोग कचरा कलेक्टर का संदर्भ लेते हैं, जो तय करता है कि जब कोई ऑब्जेक्ट (या पूरे ऑब्जेक्ट चक्र) से छुटकारा मिल सकता है। यह से बचाता है क्लासिक सी और सी ++ शैली मेमोरी लीक, जिसके द्वारा मेरा मतलब स्मृति आवंटित करना और बाद में इसे मुक्त नहीं करना है।

हालांकि, कई बार प्रोग्रामर यह महसूस नहीं करते हैं कि वस्तुओं में अभी भी संदर्भों को लटकाना है और कचरा नहीं मिला है, जिससे ... स्मृति रिसाव हो रही है।

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


94
2018-03-26 19:19



उदाहरण के लिए: ओएस विजेट का निपटान करने के लिए भूलना। - Powerlord
संदर्भ गणना के मुकाबले जीसी बहुत जटिल है, लेकिन उस हां के अलावा। सी / सी ++ में मेमोरी रिसाव "कुछ ऐसा है जो मुक्त नहीं है लेकिन अब संदर्भित नहीं है"। जावा / .NET में मेमोरी रिसाव "कुछ ऐसा है जिसे हम अभी भी संदर्भित कर रहे हैं लेकिन नहीं होना चाहिए"। बेशक .NET प्रकार के रिसाव अभी भी सी / सी ++ में हो सकते हैं, इसलिए .NET में मेमोरी लीक होने की संभावना कम है, लेकिन अभी भी बहुत संभावना है। - MK.
उच्च प्रदर्शन वर्चुअल मशीनों में संदर्भ गणना का शायद ही कभी उपयोग किया जाता है। ओवरहेड बहुसंख्यक अनुप्रयोगों के लिए भारी और हत्या है। - Dykam
+1 मुझे घटनाओं का उदाहरण पसंद आया। - Omar


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

अब, वे एक कथित स्मृति रिसाव की अवधारणा को भी इंगित करते हैं, या जैसा कि "संसाधन रिसाव" टिप्पणियों में बताया गया था, जो किसी ऑब्जेक्ट का उपयोग होता है जिसमें संदर्भ संदर्भ होते हैं और ठीक से निपटान नहीं किया जाता है। यह आईओ ऑब्जेक्ट्स, डेटासेट्स, जीयूआई तत्वों, और इसी तरह के साथ हो सकता है। वे हैं जो मैं आमतौर पर .NET के साथ काम करते समय "स्मृति रिसाव" के बराबर होता हूं, लेकिन वे पारंपरिक अर्थ में लीक नहीं होते हैं।


15
2018-03-26 19:22



कुछ .NET कक्षाएं, जैसे कि आपने उल्लेख किया है, विंडोज कर्नेल ऑब्जेक्ट्स (जैसे फ़ाइल हैंडल) को लपेटें, इसलिए उन्हें कॉल किए बिना दायरे से बाहर निकलने दें Dispose अंतर्निहित संसाधन की रिहाई में देरी हो जाती है जब तक कि जीसी अंततः इसके आसपास न हो जाए। इस प्रकार की त्रुटि फाइलों को लॉक और पहुंच से बाहर कर सकती है, इसलिए यह वास्तव में खराब है, लेकिन यह वास्तविक स्मृति रिसाव नहीं है। - Steven Sudit
@Steven हाँ एक निश्चित बिंदु पर ... लेकिन हकीकत में यह एक रिसाव है, जैसा कि आप इसे कैसे ठीक करते हैं। मुझे लगता है कि यह एक "रिसाव" की आपकी परिभाषा पर निर्भर करता है - Mitchel Sellers
शायद मैं picky जा रहा हूँ, लेकिन एक रिसाव की मेरी धारणा यह है कि एक संसाधन खो गया है स्थायी रूप से (या कम से कम प्रक्रिया बंद होने तक)। इवेंट त्रुटि एक असली रिसाव है, जबकि यह उदाहरण सिर्फ एक अवांछनीय धीमा है। फिर, यह एक अच्छा मुद्दा हो सकता है, और मैं निश्चित रूप से इस तरह की एक समस्या को तुरंत ठीक कर दूंगा। - Steven Sudit
@ स्टेवन - उपयोग के आधार पर, प्रक्रिया बंद होने तक इसे खोया जा सकता है, मैं इसे हमेशा फाइलों, एक्सएमएलएसरियलाइजर्स और कोड में अन्य ऑब्जेक्ट्स के साथ देखता हूं। - Mitchel Sellers
हैंडल हैं साधन, और उन्हें छोड़ने में विफल (निपटान) की ओर जाता है संसाधन लीक, लेकिन इसे आमतौर पर नहीं कहा जाता है याद रिसाव। - Aaronaught


कचरा संग्रह के कारण, आप नियमित मेमोरी लीक नहीं कर सकते (विशेष मामलों जैसे असुरक्षित कोड और पी / Invoke) से अलग। हालांकि, आप निश्चित रूप से अनजाने में संदर्भ हमेशा के लिए जीवित रह सकते हैं, जो प्रभावी रूप से लीक स्मृति।

संपादित करें

एक वास्तविक रिसाव अब तक मैंने देखा है कि सबसे अच्छा उदाहरण घटना हैंडलर + = गलती है।

संपादित करें

गलती के स्पष्टीकरण के लिए नीचे देखें, और उन स्थितियों के तहत जिनके तहत यह वास्तविक रिसाव के रूप में योग्य है, जो लगभग वास्तविक रिसाव के विपरीत है।


12
2018-03-26 19:22



क्या आप "ईवेंट हैंडलर + = गलती" समझा सकते हैं? मेरी अज्ञानता क्षमा करें :) - Pwninstein
@Pwninstein। यदि आप MyClass.CoolEvent + = new EventHandler (HandleCoolEvent) के साथ एक ईवेंट हैंडलर संलग्न करते हैं; यह अनिवार्य रूप से एक घटना सूची को एक आंतरिक सूची में जोड़ता है। और यदि आप मेमोरी लीक से बचना चाहते हैं, तो आपको उसी तरीके से अलग करना चाहिए लेकिन + = with - = को प्रतिस्थापित करना चाहिए। यह इवेंट हैंडलर को आंतरिक सूची से हटा देता है। - Henri
उसमें जोड़ने के लिए, यदि आप ईवेंट को हटा नहीं देते हैं (या ऑब्जेक्ट स्वयं, या दोनों, मुझे इस समय याद नहीं है) हमेशा के लिए जीतेगा, या कम से कम आपके प्रोग्राम के अंत तक। - RCIX
मैं कहूंगा कि यह केवल "सत्य" रिसाव है यदि आपके पास अब प्रतिनिधि नहीं है, तो आप नहीं कर सकते -= अगर आप चाहें तो भी। यदि आप किसी अज्ञात विधि का उपयोग करते हैं, या बाद में यदि आप क्लास इंस्टेंस के सभी संदर्भ खो देते हैं तो यह तुरंत हो सकता है (लेकिन यह अभी भी स्मृति में फंस गया है)। - Steven Sudit
मैं कहूंगा कि इस धागे में लोकप्रिय "सत्य रिसाव" की परिभाषा के आधार पर, + = योग्य नहीं है। ऐसा इसलिए है क्योंकि इस आयोजन को आयोजित करने वाली कक्षा किसी भी समय कह सकती है MyEvent = null इस प्रकार संदर्भ को हटाकर और जीसी को स्मृति मुक्त करने की इजाजत दी गई। यही कहना है, संदर्भ खुद है अभी भी उपलब्ध है, हालांकि केवल एक वर्ग के लिए। - Jeffrey L Whitledge


यहां .NET में मेमोरी लीक का एक उदाहरण दिया गया है, जिसमें असुरक्षित / पिनवोक शामिल नहीं है और इसमें ईवेंट हैंडलर भी शामिल नहीं हैं।

मान लें कि आप एक पृष्ठभूमि सेवा लिख ​​रहे हैं जो नेटवर्क पर संदेशों की एक श्रृंखला प्राप्त करता है और उन्हें संसाधित करता है। तो आप उन्हें पकड़ने के लिए एक वर्ग बनाते हैं।

class Message 
{
  public Message(int id, string text) { MessageId = id; Text = text; }
  public int MessageId { get; private set; }
  public string Text { get; private set; }
}

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

तो आप एक नई संपत्ति जोड़ते हैं ...

class Message
{
  ...
  public Message PreviousMessage { get; private set; }
  ...
}

और आप इसे सेट करने के लिए कोड लिखते हैं। और, ज़ाहिर है, मुख्य लूप में कहीं भी आपको अंतिम संदेश के साथ रखने के लिए एक चर होना चाहिए:

  Message lastMessageReceived;

फिर आपको कुछ दिनों बाद पता चला है कि आपकी सेवा ने बमबारी की है, क्योंकि उसने सभी उपलब्ध स्मृति को अप्रचलित संदेशों की एक लंबी श्रृंखला के साथ भर दिया है।


4
2018-03-26 19:40



यह खराब डिजाइन के रूप में इतना रिसाव नहीं है। यह वही कर रहा है जो पूछा गया था: सभी पिछले संदेशों को स्मृति में रखते हुए। ऐसा कोई तरीका नहीं है कि यह जान सके कि कौन से संदेश ड्रॉप करना ठीक है। - Steven Sudit
@ स्टेवन सूडिट - कंप्यूटर कभी भी ऐसा नहीं करता है जो उससे पूछा गया था? मेमोरी लीक खराब डिजाइन या छोटी गाड़ी कार्यान्वयन के कारण होते हैं। आप इस कल्पित स्थिति को एक बग या खराब डिजाइन कह सकते हैं, लेकिन, किसी भी तरह से, उद्देश्य बेकार वस्तुओं के साथ स्मृति को भरना नहीं था। - Jeffrey L Whitledge
माना जाता है, मैं picky जा रहा हूँ। मैं इसे केवल एक रिसाव मानता हूं अगर यह पूरी तरह से स्पष्ट नहीं था कि यह अनिश्चित काल तक स्मृति उपयोग में वृद्धि करेगा। आपके द्वारा दिखाए गए कोड में एक ही लक्षण है जो खराब रिसाव के रूप में होता है - स्मृति उपयोग एक दुर्घटना तक बढ़ता है - लेकिन इसका एक अलग कारण है। एक घटना हैंडलर को अनलिंक करने के लिए भूलना, हालांकि, सूक्ष्म है। - Steven Sudit
मैंने जो कहा वह मुझे स्पष्ट करने दें। सी में, यदि आप एक बफर को मॉलोक करते हैं और इसके सभी संदर्भ खो देते हैं, तो यह एक रिसाव है क्योंकि इस बिंदु पर खोया स्मृति पुनर्प्राप्त करने के लिए आपका कोड कुछ भी नहीं कर सकता है। उपर्युक्त नमूने में, कोड श्रृंखला के शीर्ष संदर्भ को "रिसाव" कर सकता है और जीसी इसे सभी को हटा देगा। यह साफ-सफाई की संभावना है जो मुझे वास्तविक रिसाव के रूप में कुछ स्वीकार करने से रोकती है। - Steven Sudit
यह एक रिसाव है, लेकिन यह एक नहीं है परंपरागत रिसाव। नेट पारंपरिक रिसाव को रोकता है, लेकिन एक गैर परंपरागत रिसाव बनाने के लिए अभी भी कई तरीके हैं। - Joel Coehoorn


यहां अन्य मेमोरी लीक हैं जो इस लड़के को एएनटीएस .NET प्रोफाइलर का उपयोग करके मिला: http://www.simple-talk.com/dotnet/.net-tools/tracing-memory-leaks-in-.net-applications-with-ants-profiler/


4
2018-03-31 15:19



दिलचस्प लिंक एएनटीएस ने मुझे यह पुष्टि करने में मदद की कि एसएमओ लीक हो रहा था, इसलिए मैं भी इसकी सिफारिश करता हूं। - Steven Sudit
+1 आखिरी नौकरी में हमने इस प्रोफाइलर का उपयोग तीसरे पक्ष के डीएल में मेमोरी रिसाव खोजने के लिए किया था जिसे हम इस्तेमाल कर रहे थे। उस स्थिति में, यह डीएल के असुरक्षित कोड में एक रिसाव हुआ और प्रबंधित कोड नहीं था, लेकिन यह अभी भी हमें लीक को खोजने में मदद करने में काफी उपयोगी था। - Dinah


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

सभी सॉफ्टवेयर स्मृति रिसाव कर सकते हैं।

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

इसके अलावा, मैंने हाल ही में स्मृति में संभावित लीकिंग के साथ आ गया है .NET-COM इंटरऑप सेटिंग। COM घटक संदर्भ गणना का उपयोग यह तय करने के लिए करते हैं कि उन्हें कब मुक्त किया जा सकता है। .NET ने अभी तक एक और संदर्भ गिनती तंत्र जोड़ा है जो स्थिर के माध्यम से प्रभावित हो सकता है System.Runtime.InteropServices.Marshal कक्षा।

आखिरकार, आपको अभी भी एक .NET प्रोग्राम में संसाधन प्रबंधन के बारे में सावधान रहना होगा।


3
2018-03-26 19:29



ऑब्जेक्ट्स को लागू करने वाले ऑब्जेक्ट्स लगभग हमेशा फाइनलाइज़र को लागू करते हैं, इसलिए अंतर्निहित संसाधन अंततः जीसी द्वारा साफ किया जाता है, हालांकि समय-समय पर जरूरी नहीं है। - Steven Sudit
हर बार नहीं। कुछ खुद को रूट करते हैं, और ऐपडोमेन बंद होने तक साफ नहीं किया जाएगा। - kyoryu
@kyor: यह दिलचस्प है। क्या आप मुझे अपने मतलब के स्व-rooting ऑब्जेक्ट के उदाहरण के लिए इंगित कर सकते हैं? - Steven Sudit


आप .NET कोड में पूरी तरह मेमोरी लीक कर सकते हैं। कुछ वस्तुओं, कुछ मामलों में, खुद को रूट करेंगे (हालांकि ये आमतौर पर हैं IDisposable)। कॉल करने में विफल Dispose() इस मामले में किसी ऑब्जेक्ट पर एक आवंटित ऑब्जेक्ट के साथ वास्तविक, सी / सी ++ स्टाइल मेमोरी लीक का कारण बन जाएगा जिसका आपके पास संदर्भ करने का कोई तरीका नहीं है।

कुछ मामलों में, कुछ टाइमर कक्षाओं में यह व्यवहार हो सकता है, एक उदाहरण के रूप में।

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

यहां कुछ नमूना कोड का उपयोग कर रहा है System.Threading.Timer

public class Test
{
    static public int Main(string[] args)
    {
        MakeFoo();
        GC.Collect();
        GC.Collect();
        GC.Collect();
        System.Console.ReadKey();
        return 0;
    }

    private static void MakeFoo()
    {
        Leaker l = new Leaker();
    }
}

internal class Leaker
{
    private Timer t;
    public Leaker()
    {
        t = new Timer(callback);
        t.Change(1000, 0);
    }

    private void callback(object state)
    {
        System.Console.WriteLine("Still alive!");
        t.Change(1000, 0);
    }
}

बहुत पसंद GLaDOS, द Leaker ऑब्जेक्ट अनिश्चित काल तक "जिंदा" होगा - फिर भी, ऑब्जेक्ट तक पहुंचने का कोई तरीका नहीं है (आंतरिक रूप से छोड़कर, और ऑब्जेक्ट को तब कैसे पता चलेगा जब इसे संदर्भित नहीं किया जाता है?)


2
2018-03-27 03:00



हालांकि, इस उदाहरण में अभी भी कोड चल रहा है। कॉलबैक विधि हर बार चलती है। यह पारंपरिक स्मृति रिसाव नहीं है जब तक कि इसके साथ जुड़े किसी भी कोड को "मृत" भी न हो। आप पारंपरिक स्मृति रिसाव बनाने के लिए इस तरह कुछ उपयोग करने में सक्षम हो सकते हैं, लेकिन जैसा कि दिखाया गया उदाहरण अभी तक योग्य नहीं है। - Joel Coehoorn


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


1
2018-03-26 19:26



+1 धन्यवाद, यह एक महत्वपूर्ण भेद है कि मुझे एहसास नहीं हुआ कि मैं एक साथ लंप रहा था। - Dinah


खैर .NET एक है कचरा इकट्ठा करने वाला जब यह फिट दिखाई देता है तो चीजों को साफ करने के लिए। यह वही है जो इसे अन्य अप्रबंधित भाषाओं से अलग करता है।

लेकिन .NET मेमोरी लीक हो सकती है। जीडीआई लीक उदाहरण के लिए, विंडोज फॉर्म अनुप्रयोगों के बीच आम हैं। मैंने जिन अनुप्रयोगों में मदद की है, उनमें से एक नियमित आधार पर इसका अनुभव विकसित करता है। और जब कार्यालय में कर्मचारी पूरे दिन कई उदाहरणों का उपयोग करते हैं तो उनके लिए विंडोज़ के लिए 10,000 जीडीआई ऑब्जेक्ट सीमा को हिट करने के लिए असामान्य नहीं है।


1
2018-03-26 19:24



क्या जीडीआई ऑब्जेक्ट्स .NET ऑब्जेक्ट्स में लपेटे गए थे? - Steven Sudit
हाँ, जीडीआई ऑब्जेक्ट सीधे .NET से बनाए जाते हैं। उदाहरण के लिए, ब्रश क्लास दृश्यों के पीछे एक ब्रश जीडीआई ऑब्जेक्ट बनाता है। कचरा कलेक्टर सामान्य रूप से इस सामान को साफ करेगा, लेकिन स्पष्ट रूप से हमें कुछ परिस्थितियां मिली हैं जहां यह नहीं होगी। वैसे भी, यह एक .NET 1.1 ऐप है जिसे हम एक WPF ऐप द्वारा प्रतिस्थापित कर रहे हैं जैसा कि हम बोलते हैं। और डब्ल्यूपीएफ जीडीआई वस्तुओं का उपयोग नहीं करता है। तो यह हल करने का एक तरीका है। - Steve Wortham
ब्रश ऑब्जेक्ट कॉल को अंतिम रूप देने में निपटान करता है, इसलिए मुझे संदेह है कि अंततः रिसाव जीसी द्वारा बढ़ाया जाएगा। फिर भी, भले ही यह उचित रिसाव न हो, फिर भी यह संसाधन जारी करने में एक अनचाहे देरी है, जो एक है मेहरबान रिसाव का - Steven Sudit


सी / सी ++ मेमोरी लीक का एक प्रमुख स्रोत है प्रभावी रूप से .NET में मौजूद नहीं है जब साझा स्मृति को डिलीकेट करना है

डिजाइनिंग .NET क्लास लाइब्रेरीज़ पर ब्रैड अब्राम के नेतृत्व वाले वर्ग से निम्नलिखित है

"ठीक है, पहला बिंदु है, ज़ाहिर है, कोई मेमोरी लीक नहीं है, है ना? नहीं? अभी भी मेमोरी लीक हैं? ठीक है, एक अलग तरह की मेमोरी रिसाव है। उसके बारे में कैसे? तो स्मृति की रिसाव की तरह हम पुरानी दुनिया में नहीं है, आप कुछ स्मृति को मॉलोक करते थे और फिर नि: शुल्क करना चाहते थे या फिर रेफरी करना चाहते थे और रिलीज करना भूल गए थे, या जो भी जोड़ी है। और नई दुनिया में, कचरा कलेक्टर अंत में सभी मेमोरी का मालिक है, और कचरा कलेक्टर उस सामान को मुक्त कर देगा जब अब कोई संदर्भ नहीं है। लेकिन फिर भी लीक की तरह हो सकती है, है ना? लीक की तरह क्या हैं? अच्छा, अगर आप उस वस्तु का जिक्र रखते हैं , तो कचरा कलेक्टर इसे मुक्त नहीं कर सकता है। तो कई बार, क्या होता है आपको लगता है कि आप वस्तुओं के पूरे ग्राफ से छुटकारा पा चुके हैं, लेकिन अभी भी एक व्यक्ति संदर्भ के साथ इसे पकड़ रहा है, और फिर आप ' फिर से अटक गया। कचरा कलेक्टर तब तक मुक्त नहीं हो सकता जब तक कि आप इसके सभी संदर्भों को छोड़ दें।

दूसरा, मुझे लगता है, एक बड़ा मुद्दा है। कोई स्मृति स्वामित्व मुद्दा नहीं है। यदि आप WIN32 API दस्तावेज़ पढ़ते हैं, तो आप देखेंगे, ठीक है, मैं पहले इस संरचना को आवंटित करता हूं और इसे पास करता हूं और फिर आप इसे पॉप्युलेट करते हैं, और फिर मैं इसे मुक्त करता हूं। या क्या मैं आपको आकार बताता हूं और आप इसे आवंटित करते हैं और फिर मैं इसे बाद में मुक्त करता हूं या आप जानते हैं, इन सभी बहसें इस बारे में चल रही हैं कि उस स्मृति का मालिक कौन है और जहां इसे मुक्त किया जाना चाहिए। और कई बार, डेवलपर्स बस उस पर छोड़ देते हैं और कहते हैं, "ठीक है, जो भी हो। ठीक है, जब एप्लिकेशन बंद हो जाता है तो यह मुफ़्त होगा, "और यह ऐसी अच्छी योजना नहीं है।

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

पूर्ण ट्रांसक्रिप्ट


1
2017-08-03 16:04