2011-02-16 11 views
26

मैं मेमोरी लीक की अवधारणा को समझने की कोशिश कर रहा हूं बेहतर कोई भी उपयोगी जानकारी इंगित कर सकता है जो मुझे बेहतर ढंग से समझने में मदद करेगा कि मेमोरी लीक क्या हैं और मैं उन्हें अपने कोड में कैसे पाउंगा।मेमोरी लीक्स सी #

धन्यवाद

+0

विंडोज रजिस्ट्री → खोज → "हीपलेकडेटेशन" – Bitterblue

+0

यहां एक ब्लॉग पोस्ट है जिसे मैंने कुछ समय पहले किया था। नेट मेमोरी लीक: http://crazorsharp.blogspot.com/2009/03/net-memory-leaks-it-is -possible.html – BFree

+4

पृथ्वी पर यह विषय कैसे है? वह मेमोरी लीक के बारे में जानना चाहता है, जो कि मेरी नम्र लेकिन सही राय में सीधे उत्तरदायी और सीधे प्रासंगिक है। –

उत्तर

3

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

10

एक बहुत अच्छा पढ़ा Everybody thinks about garbage collection the wrong way है।

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

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

मैं अत्यधिक ऊपर रेमंड चेन के लेख की अनुशंसा करता हूं, यह बहुत ही रोचक है।

22

जब आप स्मृति आवंटित करते हैं तो पारंपरिक मेमोरी रिसाव होता है, और फिर किसी भी तरह इसे मुक्त करने के लिए "भूल जाते हैं"। पुराने सी ++ कोड में, इसका मतलब है new को delete के बिना कॉल करना। सी में, इसका मतलब alloc()/malloc() पर free() के बिना एक कॉल था।

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

यह भी ध्यान रखना महत्वपूर्ण है कि सिर्फ इसलिए कि आप .NET में स्मृति उपयोग बढ़ाने के पैटर्न को देखते हैं, इसका मतलब यह नहीं है कि आपका ऐप स्मृति को लीक कर रहा है। कम समग्र स्मृति दबाव के मामलों में कचरा कलेक्टर अभी तक इकट्ठा नहीं कर सकता है, या इकट्ठा करके, लेकिन ऑपरेटिंग सिस्टम को स्मृति वापस नहीं कर सकता है।

+0

किसी भी मौके से "पुराने सी ++" स्मार्ट पॉइंटर्स के बिना सी ++ होगा? – user666412

36

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

  • को हटाने नहीं घटना श्रोताओं:

    सी # में, इन कुछ सामान्य मेमोरी लीक कर रहे हैं। किसी भी घटना श्रोता जो अज्ञात विधि या लैम्ब्डा अभिव्यक्ति के साथ बनाया गया है जो किसी बाहरी वस्तु का संदर्भ देता है, वह वस्तुओं को जीवित रखेगा। जब ईवेंट का उपयोग नहीं किया जाता है तो ईवेंट श्रोताओं को हटाने के लिए याद रखें।

  • डेटाबेस कनेक्शन या परिणाम सेट को तब तक खोलना जब उनका उपयोग नहीं किया जाता है। सभी IDisposable ऑब्जेक्ट्स पर Dispose() पर कॉल करना याद रखें। Use the using statement
  • पी/Invoke का उपयोग कर सी से फ़ंक्शंस को कॉल करें जो स्मृति को आवंटित करते हैं जिसे आप कभी रिलीज़ नहीं करते हैं।
4

"मेमोरी लीक" को "स्मृति का उपयोग किया जाना चाहिए जब आप मानते हैं कि इसका उपयोग नहीं किया जाना चाहिए" कचरा एकत्रित भाषाओं/रनटाइम पर सी #/जावा के रूप में लागू करने के लिए।

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

5

जब स्मृति किसी एप्लिकेशन को असाइन की जाती है, तो एप्लिकेशन को उस मेमोरी को ऑपरेटिंग सिस्टम पर वापस छोड़ने का दायित्व होता है ताकि इसे अन्य अनुप्रयोगों द्वारा दोबारा उपयोग किया जा सके। एक स्मृति रिसाव तब होता है जब कोई एप्लिकेशन उस स्मृति को जारी नहीं करता है, इस प्रकार इसे पुन: आवंटित करने से रोकता है।

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

Widget widget = new Widget();

कोड के ऊपर लाइन विजेट वर्ग का एक नया उदाहरण बनाता है और विजेट क्षेत्र है कि वस्तु के लिए एक संदर्भ असाइन किया गया है:

निम्नलिखित कोड पर विचार करें। जीसी प्रत्येक ऑब्जेक्ट से जुड़े संदर्भों का ट्रैक रखता है और ऑब्जेक्ट्स की स्मृति को हटा देता है जिसके लिए कोई मजबूत संदर्भ नहीं है।

यह उल्लेखनीय है कि सीएलआर का कचरा संग्रह केवल प्रबंधित वस्तुओं को एकत्र करेगा, .NET कोड अक्सर अप्रबंधित संसाधनों का उपयोग कर सकता है जो स्वचालित रूप से कचरा नहीं हो सकता है।

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

कक्षाएं जो अप्रबंधित संसाधनों का संदर्भ देती हैं, उन्हें यह सुनिश्चित करना चाहिए कि उन संसाधनों को सही ढंग से हटा दिया गया हो।ऐसा करने का एक उदाहरण है कुछ इस तरह दिखेगा: जब एक finalizer से बुलाया जा रहा है

public void ManagedObject : IDisposable 
{ 
    //A handle to some native resource. 
    int* handle; 

    public ManagedObject() 
    { 
     //AllocateHandle is a native method called via P/Invoke. 
     handle = AllocateHandle(); 
    } 

    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    private void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      //deal with managed resources here 
      FreeHandle(handle); 
     } 
    } 

    ~ManagedType() 
    { 
     Dispose(false); 
    } 
} 

disposing पैरामीटर गलत है। यह अंतिम संसाधनों के भीतर से प्रबंधित संसाधनों को रोकने के लिए है क्योंकि प्रबंधित संदर्भों को उस चरण में अमान्य माना जाना चाहिए।

ध्यान दें कि Dispose() विधि GC.SuppressFinalize(this) पर कॉल करती है जो उस उदाहरण के लिए चलने वाले अंतिमकर्ता को रोकती है। ऐसा इसलिए किया जाता है क्योंकि फाइनेंजर में जो संसाधनों को हटा दिया गया था, वे निपटान कॉल में एक फियालाइज़र आमंत्रण अनावश्यक बनाते थे।

क्लाइंट कोड है कि कक्षाओं कि अप्रबंधित संसाधन (या किसी भी वर्ग IDisposable लागू करता है) को संभालने का उपयोग एक using ब्लॉक के भीतर ऐसा करना चाहिए यह सुनिश्चित करें कि IDisposable.Dispose संसाधन के लिए उपयोग की जरूरत नहीं है, जब कहा जाता है के रूप में इस ले जाएगा बनाता है प्रबंधित और अप्रबंधित संसाधनों दोनों की देखभाल और, ऊपर दिए गए उदाहरण के मामले में, सुनिश्चित करें कि अंतिमकर्ता को एक बहुत महंगा कॉल नहीं किया गया है।

मेरे जुआ के लिए अपॉजिलीज। मैं अभी रुक जाऊंगा।

संबंधित मुद्दे