2011-10-10 26 views
5

में अपवादों को पकड़ना निम्नलिखित उदाहरण संभावित स्मृति रिसाव छोड़ देता है क्योंकि विनाशक उस वस्तु के लिए नहीं चलता है जिस पर अपवाद को उसके कन्स्ट्रक्टर के दौरान संभाला जाता है। मैं इस मेमोरी रिसाव को कहां संभाल सकता हूं?कन्स्ट्रक्टर

#include <exception> 

class MyClass { 

public: 
     MyClass() 
     { 
      c = new char[5]; 
      throw std::runtime_error("test"); 
     } 

     ~MyClass() 
     { 
      delete[] c; 
     } 

private: 
    char *c; 
}; 

int main() 
{ 
    try 
    { 
     MyClass Obj; 

    } 
    catch (std::runtime_error) 
    { 

    } 
} 

उत्तर

5

आप RAII का उपयोग कर बेहतर कर रहे हैं, इस मामले में स्मार्ट सूचक विशिष्ट होना।

या वैकल्पिक रूप से, आप Two Phased Construction रणनीति का उपयोग कर सकते हैं।

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

boost::scoped_ptr या std::tr1::scoped_ptr किसी भी कच्चे पॉइंटर्स के बजाय इस परिदृश्य के लिए उपयुक्त हैं।

+2

इस डाउनवोट के लिए क्या कॉल है? आरएआईआई इस बारे में जाने का सबसे अच्छा तरीका है, और अगर कोई अन्यथा गलत कहता है। अगर आप डाउनवोट के लिए ज़िम्मेदार महसूस करते हैं, तो हमें समझाने के लिए ज़िम्मेदार क्यों महसूस करें? और यदि आप नहीं कर सकते हैं और महसूस करते हैं * यह गलत है तो आप डाउनवॉटिंग के लिए पर्याप्त योग्य नहीं हैं, किसी और को ऐसा करने दें। –

+0

यह समाधान C++ 11 संबंधित सामग्री के आधार पर है? – user103214

+0

नहीं यह सी ++ 03 है। –

6

कन्स्ट्रक्टर में अपवाद को पकड़ें, साफ करें (अपनी याददाश्त को हटा दें), फिर स्मृति रिसाव के बिना अपवाद फेंक दें।

+0

जब मैं कन्स्ट्रक्टर में मेमोरी रिसाव के बिना अपवाद को फिर से हटा देता हूं तो विनाशक को कभी नहीं बुलाया जाता था। इस के लिए कोई कारण है? – user103214

+1

@ user974191: ऑब्जेक्ट निर्माण कन्स्ट्रक्टर की समाप्ति ब्रेस तक पूरा नहीं होता है। विनाशक केवल ऑब्जेक्ट के लिए बुलाया जाता है जो पूर्ण हो जाता है। यदि कन्स्ट्रक्टर पूरी तरह से निष्पादित नहीं किया गया था तो वस्तु मौजूद नहीं है और इसलिए कोई विनाशक नहीं कहा जाएगा। –

1

आप निर्माता शरीर में अपवाद पकड़ कर सकते हैं, आप क्या सफाई की जरूरत है, तो rethrow throw;

जिसके अनुसार, अपवाद और स्मृति के मैनुअल हैंडलिंग के साथ अपवाद अच्छी तरह से एक साथ नहीं जाते। आप उस ऑब्जेक्ट का उपयोग करके बहुत बेहतर हो जाएंगे जो स्वचालित रूप से सी सदस्य (जैसे std::string, std::vector<char>, std::unique_ptr<char[]> आदि) के लिए स्मृति का प्रबंधन करता है। यदि आप उपरोक्त में से किसी एक की तरह कक्षा लिख ​​रहे हैं जिसका उद्देश्य उस स्मृति की देखभाल करना है, तो आपको वास्तव में केवल स्मृति को प्रबंधित करने की आवश्यकता है।

4

एक तरीका है throw कन्स्ट्रक्टर की शुरुआत में सशर्त अपवाद और फिर स्मृति आवंटित करें।

MyClass() 
    { 
    if(<condition>) 
     throw std::runtime_error("test"); 
    c = new char[<SIZE>]; 
    } 

अन्य तरह से निर्माता enclosing विशेष try-catch() सिंटैक्स का उपयोग करने के लिए है:

MyClass() 
    try { 
    c = new char[5]; 
    throw std::runtime_error("test");; 
    } 
    catch(std::runtime_error e) { 
    delete[] c; 
    } 

Demo

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