2017-11-04 30 views
9

मेरा प्रश्न ढेर स्मृति से सरणी हटाने के बारे में है। मैंने एक पुस्तक और this blog और अन्य संसाधन like this one पढ़ा, और उन सभी ने कहा कि ढेर से एक सरणी हटाने के लिए हमें के बाद का उपयोग करना चाहिए ताकि अगर हम [] का उपयोग किये बिना हमारे कोड लिखते हैं तो हमने स्मृति लीक की है।ढेर से सरणी हटाना

उदाहरण के लिए, मैं valgrind पैकेज (इस पैकेज की जांच कर सकता है कि कितना लीक स्मृति बुरा कोडिंग द्वारा पैदा करता है) का उपयोग लिनक्स में .by आदेश नीचे से लिनक्स में इस छोटे से कार्यक्रम का परीक्षण किया कार्यक्रम

int *s = new int[10]; 
delete [] s; 

नीचे पर विचार करें, हमने देखा कि सब कुछ ठीक

sudo valgrind --leak-check=full ./<path_to_exe_file> 
यहाँ

है लिनक्स कमांड के उत्पादन में

==4565== HEAP SUMMARY: 
==4565==  in use at exit: 0 bytes in 0 blocks 
==4565== total heap usage: 1 allocs, 1 frees, 40 bytes allocated 
==4565== 
==4565== All heap blocks were freed -- no leaks are possible 

लेकिन मेरा प्रश्न तब दिखाई दिया जब मैं का उपयोग किए बिना [] का उपयोग किए बिना और valgrind के आउटपुट की जांच करता हूं, मैंने देखा कि सभी ढेर स्मृति मुक्त हो गई है, तो क्या यह सही है? या valgrind पता नहीं था कि पूरे ढेर को मुक्त नहीं किया गया है और सरणी का कुछ हिस्सा अभी भी वहां है !!?? और यदि valgrind इस प्रकार की लीक मेमोरी का पता नहीं लगा सका तो क्या कोई पैकेज है जो इसका पता लगा सकता है।

+0

'int * s = new int [10]; एस हटाएं; 'अपरिभाषित व्यवहार देता है। ऑपरेटर 'डिलीट' के रूप में ऑपरेटर 'नए' के ​​रूप से मेल खाना चाहिए। अपरिभाषित व्यवहार का एक संभावित अभिव्यक्ति चल रहा है जैसा कि आप उम्मीद करते हैं, जैसे आप देख रहे हैं। एक और कंपाइलर के साथ, यह अलग-अलग चला सकता है, या बिल्कुल नहीं। – Peter

+0

'हटाएं' जो आप 'नया'-एड करते हैं और 'हटाएं []' जिसे आप नया करते हैं [] '-ed। या इसके बजाय स्मार्ट पॉइंटर्स का बेहतर उपयोग करें। – Ron

+1

अपने यूबी कार्यक्रम में अपेक्षित रिसाव देखने के लिए 'int'' std :: vector 'या' std :: string' द्वारा बदलें। – Jarod42

उत्तर

5

को बिना किसी सरणी पर [] का उपयोग किए बिना अपरिभाषित व्यवहार में परिणाम। अपरिभाषित व्यवहार यह हो सकता है कि सरणी सही ढंग से हटा दी गई हो, जो कि आपने जो देखा वह प्रतीत होता है। हालांकि, आप इस पर भरोसा नहीं कर सकते हैं।

+0

के बारे में नहीं है, इसलिए मेरे प्रश्न का उत्तर आपकी पोस्ट का धन्यवाद है और अन्य टिप्पणियां यह है कि लीक मेमोरी है लेकिन 'वालग्रिंड 'इसका पता नहीं लगा सका :) –

+2

नहीं, कोई लीक नहीं है स्मृति - आप अभी भाग्यशाली हो गए हैं। –

+0

वाह मुझे नहीं पता था कि यह हो सकता है –

2

मार्टिन ब्रॉडहर्स्ट ने पहले से ही सही language-lawyer answer दिया है। का उपयोग कर delete[]delete खत्म हो गया है के बारे में

बिंदु, के लिए delete ऑपरेटर है कि क्या एक सरणी के लिए या एक ही वस्तु के लिए पारित सूचक अंक पता करने के लिए कोई रास्ता नहीं है कि वहाँ: मैं तकनीकी विस्तार जवाब देने के लिए जा रहा हूँ। इस प्रकार, delete केवल एक ही ऑब्जेक्ट हटा देता है, जबकि delete[] सरणी के आकार को पुनर्प्राप्त करने के लिए कुछ अतिरिक्त जादू का आह्वान करता है, और सभी तत्वों को हटाने के लिए आगे बढ़ता है।

अब हटाने दो अलग-अलग हिस्से होते हैं:

  1. वस्तुओं विनाशकर्ता को फोन करके नष्ट किया जाना चाहिए। एक सरणी के लिए, इसका मतलब है प्रत्येक सरणी तत्व के लिए एक विनाशक कॉल।

  2. उपयोग की जाने वाली मेमोरी को मुफ्त में चिह्नित किया जाना चाहिए ताकि इसे पुन: उपयोग किया जा सके। यह सी ++ में वैश्विक operator delete() का काम है। चूंकि सरणी लगातार संग्रहित होती हैं, इसलिए यह संपूर्ण सरणी के लिए एक एकल कॉल है।

valgrind केवल स्मृति के बारे में चिंतित है। इस प्रकार, यह malloc(), free(), operator new(), और operator delete() जैसे कार्यों आवंटित स्मृति को हुक करता है।

क्या होता है जब आप delete[] के बजाय delete पर कॉल करते हैं, तो पहली वस्तु नष्ट हो जाती है, और सूचक operator delete() पर भेज दिया जाता है।operator delete() स्मृति क्षेत्र के अंदर संग्रहीत ऑब्जेक्ट्स के बारे में नहीं जानता है, वे पहले से ही नष्ट हो चुके हैं, इसलिए यह स्मृति क्षेत्र को सफलतापूर्वक चिह्नित करेगा। valgrind यह operator delete() कॉल देखता है, और खुश है क्योंकि सभी मेमोरी पुन: उपयोग के लिए स्वतंत्र है। हालांकि, आपका कोड सभी सरणी तत्वों को ठीक से नष्ट करने में विफल रहा। और यह बुरा है।

+0

कुछ दिन पहले मैंने एक कार्यक्रम लिखा था। जब मैं इस कार्यक्रम को चलाता हूं तो कार्य पूरा करने में 2 मिनट लगते हैं !! लेकिन जब मैं 'valgrind' पैकेज का उपयोग करता हूं, तो आउटपुट केवल 3 सेकंड में तैयार होता है और मैंने अनुमान लगाया कि 'वालग्रिंड' कोड पर एक उथला दिखता है! आपके उत्तर के लिए धन्यवाद यह मेरे लिए वास्तव में सहायक है। –

+0

@ सियादामामुमी यदि कोई कार्यक्रम बिना 'वालग्रिंड' के नीचे तेजी से निष्पादित करता है, तो प्रोग्राम प्रोग्राम के साथ कुछ गलत है: 'वालग्रिंड' मूल रूप से एक नकली सीपीयू के साथ प्रोग्राम निष्पादित करता है जो प्रत्येक मेमोरी एक्सेस पर सीमा-जांच जोड़ता है, और ये सीमा-जांच लेती है पहर। 'वालग्रिंड' के तहत निष्पादित होने पर किसी भी प्रक्रिया के लिए कम से कम एक कारक 50 धीमी होने की उम्मीद है। विपरीत अर्थ यह है कि 'वालग्रिंड' के तहत चलते समय आपका प्रोग्राम कुछ अलग होता है, जिसका अर्थ है कि यह अपरिभाषित व्यवहार प्रदर्शित कर रहा है। अगर मैं तुम थे, तो मैं निश्चित रूप से इसकी जांच करूँगा। – cmaster

+0

धन्यवाद, मैं इसे जांचता हूं और रनटाइम दोनों में समान है। –

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