2009-07-29 11 views
7

यह कोड क्यों नहीं मेमोरी लीक का कारण बनता है?std :: auto_ptr, हटाएं [] और लीक

int iterCount = 1000; 
int sizeBig = 100000; 
for (int i = 0; i < iterCount; i++) 
{ 
    std::auto_ptr<char> buffer(new char[sizeBig]); 
} 

WinXP SP2, संकलक: BCB.05.03

+0

ज्यादातर मामलों में यदि आप हटाएं [] के साथ नया जोड़ते हैं और गैर-तुच्छ प्रकारों के विपरीत इसके विपरीत यह रिसाव नहीं करता है - इसके बजाय प्रोग्राम स्मृति को हटाने की कोशिश करते समय बस क्रैश हो जाता है। – sharptooth

+3

आप std :: auto_ptr –

उत्तर

15

क्योंकि आप कर रहे हैं (अन) भाग्यशाली। auto_ptr कॉल delete, delete [] पर नहीं। यह अपरिभाषित व्यवहार है।

कुछ इस तरह कर रही है और यदि आप के रूप में जीत जाएं देखने का प्रयास करें:

struct Foo 
{ 
    char *bar; 
    Foo(void) : bar(new char[100]) { } 
    ~Foo(void) { delete [] bar; } 
} 

int iterCount = 1000; 
int sizeBig = 100000; 
for (int i = 0; i < iterCount; i++) 
{ 
    std::auto_ptr<Foo> buffer(new Foo[sizeBig]); 
} 

विचार है कि यहाँ Foo के लिए अपने नाशक नहीं बुलाया जाएगा।


कारण कुछ इस तरह है: जब आप कहते हैं कि delete[] p, delete[] के कार्यान्वयन सरणी में प्रत्येक तत्व के लिए जाना है, इसके नाशक फोन है, तो मुक्त कर स्मृति पी द्वारा की ओर इशारा किया के लिए लगता है। इसी प्रकार, delete p पी पर विनाशक को कॉल करने का अनुमान है, फिर स्मृति को मुक्त करें।

char के पास विनाशक नहीं है, इसलिए यह सिर्फ पी द्वारा इंगित स्मृति को हटाने जा रहा है। उपरोक्त मेरे कोड में, यह सरणी में प्रत्येक तत्व को नष्ट करने जा रहा है (क्योंकि यह delete[] पर कॉल नहीं कर रहा है), इसलिए कुछ Foo उनके स्थानीय बार चर को हटाएंगे।

+0

के बजाय boost :: scoped_array का उपयोग करने का प्रयास कर सकते हैं हां, मैं दुर्भाग्यपूर्ण हूं :) स्पष्टीकरण के लिए धन्यवाद। – Xeningem

+0

मैंने इसे संकलित किया लेकिन मुझे '_BLOCK_TYPE_IS_VALID (pHead-> nBlockUse) 'त्रुटि संदेश मिल रहा है, प्रोग्राम क्रैश हो रहा है ..ऐसा लगता है कि यह दो बार हटा दिया जा रहा है लेकिन यह नहीं पता कि यह कैसे हो सकता है – zar

+0

'फू' के विनाशक को वास्तव में 'iterCount'time कहा जाएगा, लेकिन 'iterCount' *' sizeBig' times – zar

3

auto_ptr केवल लूप पुनरावृत्ति की अवधि के लिए ही जीवित रहेगा और पुनरावृत्ति पूर्ण होने पर उस वस्तु से जुड़ा होगा।

संकलक इस मामले में देख सकते हैं कि नई [] अंतरिक्ष उसी तरह के रूप में नई आवंटित कर सकते हैं - कहीं तत्वों की संख्या के संचय के बिना के बाद से तुच्छ char विनाशकर्ता कॉल करने के लिए कोई आवश्यकता नहीं है - और यही कारण है बाद में है जब हटाना के बजाय auto_ptr नाशक द्वारा कहा जाता है को नष्ट [] यह कोई समस्या नहीं के बाद से स्मृति ब्लॉक वास्तव में नई के रास्ते में आबंटित किया गया है और साथ हटाना है कि आवंटन बनती जा सकती है कारण बनता है।

यह ऐसा करने का एक उदाहरण है जो नहीं करना है। यह नया []नया के साथ प्रतिस्थापित करने के लिए संकलक पर निर्भर करता है या नहीं। के बजाय हटाएं [] हटाएं और इसके विपरीत अपरिभाषित व्यवहार है।

की चर्चा के लिए Why would you write something like this? (intentionally not using delete [] on an array) देखें बनाम हटाना [] को हटा दें।

+0

नोट करें ताकि जीएमएन कहता है: यह बेहद भाग्यशाली है * हटाएं * * हटाएं [] * के बराबर है? – xtofl

+1

ठीक है, हां, यह संकलक और गोपनीय रूप से डेवलपर को सहेजने की कोशिश कर रहे संकलक का परिणाम है। – sharptooth

+3

यह कंपाइलर चालाक होने का नतीजा नहीं है, बल्कि यह संकलक आलसी होने और सबसे आसान चीज करने का नतीजा है (इस मामले में इसका मतलब है कि पीओडी शामिल होने पर एक तत्व और सरणी के लिए स्मृति आवंटन ठीक वही काम करता है)। बेशक यह यू.बी. है, इसलिए यह "सराहनीय किस्मत" है कि यह किसी दिए गए कार्यान्वयन में काम करता है - और आईआईआरसी कुछ वास्तविक कार्यान्वयन हैं जहां यह काम नहीं करता है। –

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