.NET

2008-08-21 3 views
20

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

मैं दो के बारे में पता:

  1. नहीं ठीक से संयुक्त राष्ट्र: पंजीयन Event Handlers/Delegates
  2. नहीं विण्डोज़ फॉर्म्स में गतिशील बच्चे नियंत्रण निपटान:

उदाहरण:

// Causes Leaks 
Label label = new Label(); 
this.Controls.Add(label); 
this.Controls.Remove(label); 

// Correct Code 
Label label = new Label(); 
this.Controls.Add(label); 
this.Controls.Remove(label); 
label.Dispose(); 

अद्यतन: विचार सामान्य कठिनाइयों जो भी स्पष्ट हो (जैसे कि के रूप में) नहीं हैं सूचीबद्ध करने के लिए है। आम तौर पर धारणा यह है कि कचरा कलेक्टर की वजह से मेमोरी लीक बड़ी समस्या नहीं है। ऐसा नहीं लगता कि यह सी ++ में होता था।


महान चर्चा दोस्तों, लेकिन मुझे स्पष्ट ... परिभाषा से, अगर वहाँ कोई संदर्भ .NET में एक वस्तु के लिए छोड़ दिया है, यह कुछ समय में कचरा एकत्र हो जाएगा करते हैं। तो यह स्मृति रिसाव प्रेरित करने का एक तरीका नहीं है।

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

तो, ऐसे मेमोरी रिसाव कितने संभावित तरीकों से हो सकते हैं?

+2

जैसा किथ ने कहा, आपका नमूना स्मृति रिसाव का कारण नहीं बनता है। – tobsen

उत्तर

5

फ़ाइनलाइज़र थ्रेड को अवरुद्ध करें। फाइनलज़र थ्रेड अनब्लॉक होने तक कोई अन्य ऑब्जेक्ट कचरा नहीं होगा। इस प्रकार इस्तेमाल की गई स्मृति की मात्रा बढ़ेगी और बढ़ेगी।

अतिरिक्त पठन: http://dotnetdebug.net/2005/06/22/blocked-finalizer-thread/

+11

इसका क्या अर्थ है? –

+0

फाइनलाइज़र सिंगल-थ्रेडेड है। 'अंतिमकरण' तब होता है जब एक वस्तु जिसे निपटान किया जा सकता है, अंत में, निपटाया जाता है। यदि एक विशेष वस्तु का निपटारा नहीं किया जा सकता है, तो कुछ भी निपटान नहीं किया जाता है, और आप स्मृति से बाहर हो जाते हैं। –

+0

तो क्या तब संदर्भ में 'ब्लॉक' का क्या मतलब है - ओवरराइड और कोड-लपेट finalizer समारोह, या पूरी तरह से चलने से रोकने के? – Hardryv

14

एक व्यापक सूची प्रदान करने का कोई तरीका नहीं है ... यह पूछने की तरह है कि "आप गीले कैसे हो सकते हैं?"

यह कहा गया है कि, सुनिश्चित करें कि आप IDISposable लागू करने वाली सभी चीज़ों पर निपटान() को कॉल कर रहे हैं, और सुनिश्चित करें कि आप किसी भी प्रकार के अप्रबंधित संसाधनों का उपभोग करने वाले किसी भी प्रकार पर IDISposable लागू करें।

हर बार और फिर, उस कोड को लागू करने में आपकी सहायता के लिए अपने कोडबेस पर FxCop की तरह कुछ चलाएं - आपको आश्चर्य होगा कि कुछ डिस्पोजेबल ऑब्जेक्ट्स को एप्लिकेशन फ्रेमवर्क में कितना गहरा कर दिया जाएगा।

+0

आप उस नियम को लागू करने के लिए FxCop कैसे सेट अप करेंगे? – Joel

2

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

दूसरे शब्दों में, वे उन व्यक्तियों का संदर्भ लेते हैं जो उन्हें याद करते हैं कि स्मृति लीक को पता नहीं था या भूल गया था।

संपादित करें: या वे कचरा कलेक्टर या गैर-प्रबंधित कोड में वास्तविक बग हैं।

संपादित करें 2: इस बारे में सोचने का एक और तरीका हमेशा यह सुनिश्चित करना है कि आपकी वस्तुओं के बाहरी संदर्भ उचित रूप से जारी किए जाएं। बाहरी नियंत्रण आपके नियंत्रण के बाहर कोड। कोई भी मामला जहां ऐसा होता है वह एक ऐसा मामला है जहां आप स्मृति को "रिसाव" कर सकते हैं।

0

अप्रबंधित भाषाओं में स्मृति लीक का कारण बनने वाली कई चीजें अभी भी प्रबंधित भाषाओं में स्मृति रिसाव का कारण बन सकती हैं। उदाहरण के लिए, bad caching policies मेमोरी लीक में परिणाम हो सकता है।

लेकिन ग्रेग और डैनी ने कहा है कि, कोई व्यापक सूची नहीं है। कुछ भी जो इसके उपयोगी जीवनकाल के बाद स्मृति पकड़ने के परिणामस्वरूप रिसाव का कारण बन सकता है।

2

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

+2

कोई रास्ता नहीं। .NET में कॉम्पैक्ट फ्रेमवर्क पर विकसित करें और आप जल्दी से पता लगाएंगे कि यदि आप अपनी ऑब्जेक्ट्स का सही तरीके से निपटान नहीं करते हैं तो आपको जल्दी से स्मृति से बाहर निकलता है ताकि आपको वास्तव में यहां सामान्यीकृत नहीं करना चाहिए। आप जीसी के लिए ऐसा करने की प्रतीक्षा नहीं कर सकते। –

21

यह वास्तव में लीक का कारण नहीं है, यह सिर्फ जीसी के लिए और अधिक काम करता है:

// slows GC 
Label label = new Label(); 
this.Controls.Add(label); 
this.Controls.Remove(label); 

// better 
Label label = new Label(); 
this.Controls.Add(label); 
this.Controls.Remove(label); 
label.Dispose(); 

// best 
using(Label label = new Label()) 
{ 
    this.Controls.Add(label); 
    this.Controls.Remove(label); 
} 

चारों ओर झूठ बोल रही है की तरह इस नेट की तरह किसी प्रबंधित परिवेश में बड़ी समस्या नहीं है डिस्पोजेबल घटकों छोड़कर - कि प्रबंधित साधनों का एक बड़ा हिस्सा है।

आप निश्चित रूप से आपको ऐप धीमा कर देंगे। लेकिन आप किसी और चीज के लिए गड़बड़ी नहीं छोड़ेंगे।

+1

नियंत्रण झूठ बोलना बहुत खतरनाक है। छोटे फेंकने वाले अनुप्रयोगों के लिए यह ठीक है, लेकिन आपको हमेशा वास्तविक अनुप्रयोगों में उनका निपटान करना चाहिए या आपको पछतावा होगा। मेरा विश्वास करो, मैं वहां गया हूं। – Niki

+1

मैं इस पर आया, यह एक खतरनाक चीज है - आसपास के डिस्पोजेबल छोड़कर! इसका परीक्षण करने के लिए, एक लूप में System.Drawing.Bitmap बनाएं और छोड़ें - आपको जल्द ही OutOfMemoryException मिल जाएगा, और जीसी मदद नहीं करेगा। –

+1

@modosansreves - हाँ जो निश्चित रूप से आपके ऐप को तोड़ देगा। हालांकि, क्योंकि आपको प्रबंधित 'OutOfMemoryException' मिलता है, आप बस उस ऐप को क्रैश करते हैं।एक अप्रबंधित स्मृति रिसाव बीएसओडी, लटका या अन्यथा पूरी मशीन दुर्घटनाग्रस्त हो जाएगा। – Keith

4

अप्रत्याशित संसाधनों को सही ढंग से निपटाने से रोकने के तरीकों को अंतिम रूप देने (या अंतिमकर्ता से कॉल का निपटान) में अपवाद। एक सामान्य प्रोग्रामर मानते हैं कि ऑर्डर ऑब्जेक्ट्स का निपटारा किया जाएगा और पीयर ऑब्जेक्ट्स को रिलीज़ करने का प्रयास किया जा रहा है जो पहले से ही डिस्पोजेड हो चुके हैं जिसके परिणामस्वरूप अपवाद और बाकी को अंतिम रूप देने/समाप्त करने के तरीके को अंतिम रूप दिया जा सकता है।

0

गतिरोध धागे जड़ों कभी नहीं जारी करेंगे। जाहिर है आप तर्क दे सकते हैं कि डेडलॉक एक बड़ी समस्या प्रस्तुत करता है।

एक गतिरोध finalizer धागा चलाने के लिए और इस प्रकार है (जैसा कि वे अभी भी freachable सूची द्वारा निहित किया जा रहा है) फिर से दावा किया जा रहा से सभी finalizable वस्तुओं को रोकने के लिए सभी शेष finalizers कर पाएगा।

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

बड़े ऑब्जेक्ट ढेर को संकुचित नहीं किया जाता है, इसलिए आप विखंडन के माध्यम से स्मृति को रिसाव कर सकते हैं।

ऐसी कई वस्तुएं हैं जिन्हें मैन्युअल रूप से मुक्त किया जाना चाहिए। जैसे बिना पट्टे और असेंबली वाले वस्तुओं को रिमोट करना (ऐपडोमेन को अनलोड करना होगा)।

14

BindingSource वर्ग (http://msdn.microsoft.com/en-us/library/system.windows.forms.bindingsource.aspx) का एक उदाहरण का उपयोग किए बिना सीधे GridControl.DataSource गुण को सेट।

यह मेरी अनुप्रयोग है कि मुझे एक प्रोफाइलर के साथ नीचे ट्रैक करने के लिए काफी समय लगा में लीक की वजह से है, अंत में मैं इस बग रिपोर्ट है कि माइक्रोसॉफ्ट के लिए प्रतिक्रिया व्यक्त पाया: http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=92260

यह हास्यास्पद है कि BindingSource वर्ग माइक्रोसॉफ्ट के लिए दस्तावेज में एक कानूनी रूप से अच्छी तरह से सोचा वर्ग के रूप में इसे पारित करने का प्रयास करें, लेकिन मुझे लगता है कि उन्होंने मुद्रा प्रबंधकों और ग्रिड नियंत्रणों के लिए बाध्यकारी डेटा के संबंध में मौलिक रिसाव को हल करने के लिए इसे बनाया है।

इस के लिए देखें, मुझे यकीन है कि इस वजह से वहां बहुत कम रिसाव अनुप्रयोग हैं!

+7

दुष्ट पोस्ट। हम जानते हैं कि हम मेहनती सफाई संसाधनों और यह सुनिश्चित करें सब कुछ को लागू करने IDisposable का ध्यान रखा जाता है बना रही किया गया है एक मोबाइल एप्लिकेशन मिल गया है। इसके बाद भी, भारी उपयोग के बाद भी मैदान में अजीब दुर्घटना हुई थी .. हमारे पास यह सटीक परिदृश्य था! आपने धमाल मचाया। –

+1

lol +1 चटाई Nadrofsky टिप्पणी के लिए – Drevak

1
  1. उन ऑब्जेक्ट्स के संदर्भों को ध्यान में रखते हुए जिनकी आपको अब आवश्यकता नहीं है।

अन्य टिप्पणियां - यह सुनिश्चित करने के लिए एक तरीका है कि निपटान का उपयोग करने के लिए उपयोग किया जाता है ... जब कोड संरचना इसे अनुमति देता है।

2

नेट मेमोरी लीक रोकने के लिए:

1) 'का उपयोग' निर्माण को रोजगार (या 'कोशिश-अंत में निर्माण) जब भी साथ एक वस्तु' IDisposable 'इंटरफ़ेस बनाई गई है।

2) कक्षाएं 'आईडीस्पोजेबल' बनाएं यदि वे धागे बनाते हैं या वे एक स्थिर या लंबे समय तक रहने वाले संग्रह में ऑब्जेक्ट जोड़ते हैं। याद रखें एक सी # 'घटना' एक संग्रह है।

यहां Tips to Prevent Memory Leaks पर एक संक्षिप्त लेख है।

Region oldClip = graphics.Clip; 
using (Region newClip = new Region(...)) 
{ 
    graphics.Clip = newClip; 
    // draw something 
    graphics.Clip = oldClip; 
} 

स्मृति रिसाव कहाँ है:

1

एक बात है कि मेरे लिए वास्तव में अनपेक्षित था है? ठीक है, आपको oldClip भी निपटाया जाना चाहिए था! चूंकि Graphics.Clip दुर्लभ गुणों में से एक है जो हर बार गेटर का आह्वान करने पर एक नया डिस्पोजेबल ऑब्जेक्ट देता है।

3

मैं इस चर्चा में जोड़ने के लिए 4 अतिरिक्त आइटम नहीं हैं:

  1. समाप्त धागे (Thread.Abort()) है जो ठीक से इस तरह की घटना के लिए तैयारी के बिना यूआई नियंत्रण बनाया है स्मृति को जन्म दे सकती उम्मीद के इस्तेमाल किया जा रहा ।

  2. पिनवोक के माध्यम से अप्रबंधित संसाधनों तक पहुंचने और उन्हें साफ करने से स्मृति रिसाव हो सकता है।

  3. बड़ी स्ट्रिंग ऑब्जेक्ट्स को संशोधित करना। एक बार स्कोप से बाहर एक मेमोरी रिसाव नहीं, जीसी इसका ख्याल रखेगा, हालांकि, प्रदर्शन के अनुसार, यदि बड़ी तारों को अक्सर संशोधित किया जाता है तो आपका सिस्टम हिट कर सकता है क्योंकि आप वास्तव में जीसी पर निर्भर नहीं कर सकते हैं ताकि आपके प्रोग्राम का पैर प्रिंट सुनिश्चित हो सके। कम से कम।

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

1

टेस फर्नांडीज मेमोरी लीक खोजने और डिबग करने के बारे में महान ब्लॉग पोस्ट हैं। Lab 6Lab 7

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