2009-05-29 6 views
9

हैं?अपवाद एक निर्माता से .NET में कोई मेमोरी लीक जब मैं निम्नलिखित की तरह एक निर्माता से एक अपवाद फेंक फेंकने

class Victim 
{ 
    public string var1 = "asldslkjdlsakjdlksajdlksadlksajdlj"; 

    public Victim() 
    { 
     //throw new Exception("oops!"); 
    } 
} 

क्या विफल वस्तुओं को कचरा कलेक्टर द्वारा एकत्र किया जाएगा?

+0

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

उत्तर

23

सामान्य तौर पर इस स्मृति लीक नहीं के नजरिए से सुरक्षित है। लेकिन अगर आप इस प्रकार के अप्रबंधित संसाधन आवंटित करते हैं तो एक निर्माता से अपवाद फेंकना खतरनाक है। निम्न उदाहरण

public class Foo : IDisposable { 
    private IntPtr m_ptr; 
    public Foo() { 
    m_ptr = Marshal.AllocHGlobal(42); 
    throw new Exception(); 
    } 
    // Most of Idisposable implementation ommitted for brevity 
    public void Dispose() { 
    Marshal.FreeHGlobal(m_ptr); 
    } 
} 

इस वर्ग लो स्मृति हर बार जब आप बनाने के लिए भले ही आप एक का उपयोग कर ब्लॉक का उपयोग करने की कोशिश का रिसाव हो जाएगा। उदाहरण के लिए, यह स्मृति को रिसाव करता है।

using (var f = new Foo()) { 
    // Won't execute and Foo.Dispose is not called 
} 
+0

, यह स्पष्ट करना न केवल कथन का उपयोग के शरीर पर अमल नहीं करता है कि आवश्यकता है ... लेकिन फू की विधि .Dispose() कहा जाता है प्राप्त करता है। – jrista

+0

@jrista अद्यतन – JaredPar

+0

मैं गंभीरता से देर से पार्टी के लिए यहाँ हूँ, लेकिन एक कोशिश अंत में निर्माता में इस मुद्दे के बिना इसे ठीक नहीं होगा? – Gusdor

2

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

1

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

+2

"उन्हें अंतिम रूप देने या निपटाने() में फेंकना बहुत खराब है।" इसे निपटाने में फेंकने के लिए स्वीकार्य हो सकता है - उदाहरण के लिए फ़ाइलस्ट्रीम फेंक देगा अगर यह स्ट्रीम फ्लश करने में असमर्थ है (उदा। नेटवर्क त्रुटि के कारण)। यदि आप कर सकते हैं फेंक से बचें, लेकिन अगर आप चाहिए ऐसा करते हैं। FileStream के मामले में, अपवाद निगलने, फेंकने की तुलना में अधिक खतरनाक हो के रूप में यह धारणा है कि फोन करने वाले फ़ाइल सफलतापूर्वक लिखा गया था देना होगा। क्योंकि कोई उदाहरण() पर .Dispose कॉल करने के लिए बनाया गया था – Joe

4

मजेदार, क्योंकि मैंने कल similar question के साथ मदद की थी।

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

9

एक निर्माता से फेंकने अपवाद ठीक होना चाहिए आप कोई अप्रबंधित संसाधनों बनाया है, तो। हालांकि, अगर आप कन्स्ट्रक्टर में अप्रबंधित संसाधन बनाते हैं, तो उस कन्स्ट्रक्टर के पूरे शरीर को फेंकने सहित, कोशिश/पकड़ में लपेटा जाना चाहिए। JaredPar के महान उदाहरण चोरी करने के लिए:

public class Foo : IDisposable { 
    private IntPtr m_ptr; 
    public Foo() { 
    try 
    { 
     m_ptr = Marshal.AllocHGlobal(42); 
     throw new Exception(); 
    } 
    catch 
    { 
     Dispose(); 
     throw; 
    } 
    } 
    // Most of Idisposable implementation ommitted for brevity 
    public void Dispose() { 
    Marshal.FreeHGlobal(m_ptr); 
    } 
} 

निम्नलिखित अब काम करेगा:

using (var f = new Foo()) { 
    // Won't execute, but Foo still cleans itself up 
} 
संबंधित मुद्दे