2012-06-21 10 views
7

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

मेरे पास एक परीक्षण दोहन है जो त्रुटि को पुन: उत्पन्न कर सकता है। एक निश्चित वर्ग के finalizer में सांत्वना देने मैं लिखने

public class Foo 
{ 
    // Ctor 
    public Foo() 
    { 
    } 

    ~public Foo() 
    { 
     Console.WriteLine("Foo Finalized"); 
    } 
} 

परीक्षण दोहन में, मैं फू (जो बारी में बनाता है और अन्य प्रकार के सैकड़ों के साथ सूचना का आदान प्रदान) का एक उदाहरण बनाने रहा हूँ तो यह दूर करने और लागू कचरा इकट्ठा करने वाला।

मुझे लगता है कि फू फ़ाइनलाइज़र कभी नहीं कहा जाता है। मेरे पास इस सेटअप के साथ एक समान वर्ग है जिसे नियंत्रण परीक्षण के रूप में अंतिम रूप दिया गया है।

तो मेरे सवाल यह है:

मैं वाणिज्यिक या खुले स्रोत उपकरण वास्तव में क्या फू के लिए एक संदर्भ रखा है का उपयोग करते हुए निर्धारित कर सकते हैं कैसे?

मेरे पास डॉटट्रेस मेमोरी प्रोफाइलर के लिए एक पेशेवर लाइसेंस है लेकिन सहायता फ़ाइलों से इसका पता नहीं लगाया जा सकता है।

अद्यतन: मैं अब dotMemory 4.0 है, जो (अच्छा है, लेकिन व्यर्थ) dotTrace मेमोरी 3.5 का उत्तराधिकारी है का उपयोग कर रहा हूँ।

+1

यदि आपके पास पहले से ही एक प्रोफाइलर इसका उपयोग करना सीखता है - मैंने डॉटट्रेस के साथ बहुत कुछ काम नहीं किया है, लेकिन मैं अन्य दो उपयोग-पैटर्न में समान हैं और कुछ को "इनरिंग" की आवश्यकता है – Carsten

+0

@ CarstenKönig +1, मैं अब dotTrace में खुदाई कर रहा हूँ। पता लगाया गया है कि मैं नामस्थान द्वारा एक अनजान वस्तुओं को सूचीबद्ध कर सकता हूं (इसलिए मेरा अपमानजनक फू पाया गया) और उनके संदर्भ में क्या संदर्भ है, फिर नामस्थान (सैकड़ों) द्वारा फ़िल्टर किया गया, अब संदिग्ध ईवेंट हैंडलर आदि की एक सूची के माध्यम से जा रहा है ... –

+0

@ CarstenKönig वास्तव में, यह dotTrace का उपयोग कर पाया! इसमें gcroot -> Foo से ग्राफ़ में ड्रिल करने की सुविधा है, खोजने के लिए थोड़ा मुश्किल है। चीयर्स :) –

उत्तर

3

finalizer निर्धारणात्मक नहीं बुलाया जाता है, इसलिए इसे का उपयोग एक विश्वसनीय तरीके से काम को ट्रैक करने में सावधान रहना। यदि आप फाइनलाइज़र को हटाते हैं और इसके बजाय WeakReference<Foo> का उपयोग करते हैं तो आपको यह निर्धारित करने में सक्षम होना चाहिए कि ऑब्जेक्ट एकत्र किया गया था या नहीं।

सभी मेमोरी प्रोफाइलर्स इस तरह की कोई समस्या नहीं ढूंढ पाएंगे, लेकिन विभिन्न कठिनाई के साथ। मैंने व्यक्तिगत रूप से एएनटीएस का उपयोग किया है जो बहुत आसान है, लेकिन मुफ्त नहीं है। यह आपको जीयू रूट ऑब्जेक्ट से सभी तरह से Foo इंस्टेंस में संदर्भ आरेख दिखाने में मदद करेगा। इस आरेख को देखकर आमतौर पर संदर्भ रखना आसान होता है।

2

आप मेमोरी लीक की पहचान करने के लिए मेमोरी प्रोफाइलर्स का उपयोग कर सकते हैं। यहाँ कुछ,

MemProfiler

ANTS Profiler

+0

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

6

एक्सटेंशन पर look है (यह मुफ़्त है, विज़ुअल स्टूडियो के भीतर उपयोग किया जा सकता है)।

आपको रीसेट प्राप्त करने के लिए this और this सहायक मिल सकता है।

आप succefully एसओएस की स्थापना की है, तो (यह कभी कभी मुश्किल हो सकता है), जानते हुए भी क्या क्या है के रूप में आसान के रूप में

// load sos 
.load sos 
// list of all instances of YourTypeName in memory with their method tables 
!DumpHeap -type YourTypeName 
// put here the method table displayed by the previous command 
// it will show you the memory address of the object 
!DumpHeap -mt 07f66b44    
// displays information about references the object at the specified address 
!GCRoot 02d6ec94 
+0

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

1

सबसे पहले आप एक finalizer उपयोग नहीं करना चाहिए के लिए एक संदर्भ रखती है, क्योंकि:

जब finalizer कचरा दौरान कार्यान्वित

  • सही समय:

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

  • दो ऑब्जेक्ट्स के फाइनलर को किसी भी विशिष्ट क्रम में चलाने की गारंटी नहीं है, भले ही एक ऑब्जेक्ट दूसरे को संदर्भित करता हो। यही है, यदि ऑब्जेक्ट ए में ऑब्जेक्ट बी का संदर्भ है और दोनों में फाइनलाइज़र हैं, ऑब्जेक्ट बी ऑब्जेक्ट ए के प्रारंभकर्ता के प्रारंभ होने पर पहले से ही अंतिम रूप दिया जा सकता है।

  • धागा जिस पर फाइनलज़र चलाया जाता है वह अनिर्दिष्ट है।

उद्धरण से: http://msdn.microsoft.com/en-us/library/system.object.finalize.aspx
मैं बजाय निपटान विधि का उपयोग कर सुझाव है।

दूसरा, कोई भी स्मृति प्रोफाइलर उन संदर्भों को प्राप्त करने में सक्षम होना चाहिए। व्यक्तिगत रूप से मैं एएनटीएस प्रोफाइलर का उपयोग कर रहा था, यह एक बहुत अच्छा टूल है और इसमें काफी समृद्ध दस्तावेज है। आप इस दस्तावेज़ को पढ़ने का प्रयास कर सकते हैं: http://downloads.red-gate.com/HelpPDF/ANTS_Memory_Profiler/InstanceCategorizer.pdf इंस्टेंस वर्गीकरण ऑब्जेक्ट्स के सेट से जीसी रूट तक संदर्भों की श्रृंखला प्रदर्शित करता है।

+0

जबकि आप पूरी तरह से सही हैं, कुछ मामलों में इसे अंतिम रूप से उपयोग करने के लिए वास्तव में आवश्यक है। विचार करें कि आपने 3 डी सतहों को प्रस्तुत करने के लिए एक कस्टम नियंत्रण बनाया है जिसे आप अंतिम उपयोगकर्ताओं को फिर से वितरित करते हैं। अंतिम उपयोगकर्ता कॉल करने के लिए बहुत ही संभावना नहीं हैं। एक बार जब यह उपयोग में नहीं आता है तो अपने नियंत्रण पर।() का उपयोग करें। वे उम्मीद करते हैं कि यह 'बस काम करें'। इसके अलावा डब्ल्यूपीएफ कचरा कभी-कभी विचारों को इकट्ठा करता है जब वे टेम्पलेट किए जाते हैं और टैब-कंट्रोल में और टैबबैड आउट होते हैं। इन मामलों में कॉल करना असंभव है। डिस्प्ले और फाइनेंजर अप्रबंधित संसाधनों को सीधे कॉल करके आपके लिए निपटान का सबसे अच्छा विकल्प है, यदि आप पहले से ही नहीं –

6

मेमोरी लीक डिबगिंग काफी शामिल प्रक्रिया हो सकती है और आपके प्रोग्राम तर्क और कम से कम कुछ .NET आंतरिक (विशेष रूप से कचरा कलेक्टर व्यवहार) की पूरी समझ की आवश्यकता होती है।

अधिक जानकारी देखने के लिए निम्न लिंक के लिए:

अच्छा परिचय

पाठ्यक्रम हाथों पर:

जीसी और।नेट internals

एसओएस विस्तार के साथ WinDbg

गुड लक!

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