2008-10-13 13 views
174
Foo* set = new Foo[100]; 
// ... 
delete [] set; 

आप सरणी की सीमाओं को delete[] पर पास नहीं करते हैं। लेकिन वह जानकारी कहाँ संग्रहित है? क्या यह मानकीकृत है?ऑपरेंड सरणी के आकार को [] "पता" कैसे हटाता है?

+0

http://sourceforge.net/projects/fastmm/ खुला स्रोत है और मेमोरी-मैनेजर को प्रतिस्थापित करता है। यहां आप यह जान सकते हैं कि मेमोरी प्रबंधन कैसे काम करता है और कहां आवंटित करने और हटाने के लिए सूचनाएं आती हैं। –

+0

ध्यान दें कि FastMM केवल डेल्फी/सी ++ बिल्डर कंपाइलर्स के लिए विशिष्ट है, यह सी ++ के लिए सामान्य उद्देश्य मेमोरी मैनेजर नहीं है। यह सी ++ में भी लिखा नहीं है। –

उत्तर

121

जब आप ढेर पर स्मृति आवंटित करते हैं, तो आपका आवंटक ट्रैक करेगा कि आपने कितनी मेमोरी आवंटित की है। यह आमतौर पर आपके द्वारा आवंटित स्मृति से पहले "हेड" सेगमेंट में संग्रहीत होता है। इस तरह जब स्मृति को मुक्त करने का समय होता है, तो डी-आवंटक जानता है कि कितनी मेमोरी मुक्त है।

+2

ध्यान दें कि यह केवल C++ में सरणी आवंटन पर लागू होता है। अन्य सभी आवंटन प्रकार के आकार पर भरोसा करते हैं। कुछ पुस्तकालय सभी आवंटन आकारों को स्टोर करते हैं, आमतौर पर केवल डिबगिंग मोड में। –

+72

बिल्कुल कोई कारण नहीं है कि यह जानकारी प्रोग्रामर के लिए क्यों उपलब्ध नहीं होनी चाहिए। मैं एक फंक्शन में एक पॉइंटर पास कर सकता हूं और इसे मुक्त कर सकता हूं, लेकिन उसी फंक्शन में खुद को आकार प्राप्त करने के लिए मुझे एक अतिरिक्त पैरामीटर पास करना होगा। क्या इसका कोई मतलब है? –

+21

@ मार्क, यह एक * छोटी * समझ में आता है, क्योंकि सिद्धांत में यह आवंटित * ​​आवंटित * ​​ब्लॉक (जो * अनुरोध * ब्लॉक के आकार से भिन्न हो सकता है) के आकार को हमेशा स्टोर करने के लिए मुक्त करता है। कुछ आवंटन डिज़ाइनों को इस जानकारी को अपने उद्देश्यों के लिए आवश्यक हो सकता है, या गैर-सरणी ढेर आवंटन के आकार को ट्रैक करने के लिए प्रकार की जानकारी का उपयोग करने के लिए पर्याप्त परिष्कृत नहीं हो सकता है। आवंटित अनुरोधित आकार को संग्रहीत करने के लिए मजबूर करना (ताकि आप नहीं करेंगे सरणी आकार को स्वयं पास करने की आवश्यकता है) एक छोटा सा घेरा हो सकता है, लेकिन यह कल्पनाशील आवंटन डिज़ाइन पर प्रदर्शन प्रभाव हो सकता है। –

3

यह कुछ ऐसा नहीं है जो कल्पना में है - यह कार्यान्वयन निर्भर है।

2

क्योंकि 'हटाया' सरणी को 'नए' ऑपरेटर के एक ही उपयोग के साथ बनाया जाना चाहिए था। 'नए' ऑपरेशन ने उस जानकारी को ढेर पर रखा होगा। अन्यथा, नए पता के अतिरिक्त उपयोग कैसे करेंगे जहां ढेर समाप्त होता है?

0

यह मानकीकृत नहीं है। माइक्रोसॉफ्ट के रनटाइम में नया ऑपरेटर malloc() का उपयोग करता है और डिलीट ऑपरेटर मुफ्त() का उपयोग करता है। इसलिए, इस सेटिंग में आपका प्रश्न निम्न के बराबर है: मुक्त() ब्लॉक के आकार को कैसे जानता है?

दृश्यों के पीछे कुछ बहीखाता चल रही है, यानी सी रनटाइम में।

+4

सच नहीं है। नि: शुल्क कॉल करने से पहले, हटाएं [] को पहले विनाशकों को कॉल करने की आवश्यकता है। इस जानकारी के लिए कुल आवंटन आकार पर्याप्त नहीं है। दरअसल नया [] और हटाएं [] वीसी ++ में सादे और विनाशकारी प्रकारों के लिए अलग-अलग काम करता है। – Suma

7

जानकारी मानकीकृत नहीं है। हालांकि इस जानकारी पर मैंने जिन प्लेटफॉर्म पर काम किया है, उनमें पहले तत्व से पहले स्मृति में संग्रहीत किया गया है। इसलिए आप सैद्धांतिक रूप से इसका उपयोग कर सकते हैं और इसका निरीक्षण कर सकते हैं, हालांकि यह इसके लायक नहीं है।

यही कारण है कि जब आप हटाए गए सरणी संस्करण को जानते हैं कि (और कहां) इसे सही मात्रा में स्मृति मुक्त करने की आवश्यकता है - और कहें तो कॉल को हटाएं [] वस्तुओं के लिए विनाशकों की उचित संख्या।

2

यह संकलक विशिष्ट होने के लिए सी ++ मानक में परिभाषित किया गया है। जिसका मतलब कंपाइलर जादू है। यह कम से कम एक प्रमुख मंच पर गैर-तुच्छ संरेखण प्रतिबंधों के साथ तोड़ सकता है।

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

ध्यान रखें कि operator new[]/operator delete[]! = new[]/delete[]

प्लस, यह ऑर्थोगोनल है कि सी malloc द्वारा आवंटित स्मृति के आकार को कैसे जानता है।

4

मूल रूप से के रूप में स्मृति में अपनी व्यवस्था की:

[जानकारी] [मेम के लिए कहा के लिए ...]

कहाँ जानकारी अपने संकलक द्वारा इस्तेमाल किया आवंटित स्मृति की मात्रा है, और क्या स्टोर करने के लिए संरचना है नहीं।

यह कार्यान्वयन हालांकि निर्भर है।

10

कंपाइलर्स के दृष्टिकोण में से एक को थोड़ा और स्मृति आवंटित करना और एक प्रमुख तत्व में तत्वों की गिनती को स्टोर करना है।

उदाहरण यह कैसे किया जा सकता है:

यहाँ

int* i = new int[4]; 

संकलक sizeof(int)*5 बाइट्स आवंटित करेगा।

int *temp = malloc(sizeof(int)*5) 

स्टोर करेगा "4" पहले sizeof(int) बाइट्स

*temp = 4; 

में और 4 तत्वों की एक सरणी के लिए i

i = temp + 1; 

तो i होगा अंक निर्धारित करते हैं, नहीं 5.

और हटाने

delete[] i; 

निम्नलिखित तरीके से कार्रवाई की जाएगी:

int *temp = i - 1; 
int numbers_of_element = *temp; // = 4 
... call destructor for numbers_of_element elements 
... that are stored in temp + 1, temp + 2, ... temp + 4 if needed 
free (temp) 
0

यह एक और अधिक दिलचस्प समस्या यह है की तुलना में आप पहली बार में सोच सकते हैं। यह उत्तर लगभग एक संभावित कार्यान्वयन है।

सबसे पहले, जबकि कुछ स्तर पर आपके सिस्टम को यह पता होना चाहिए कि स्मृति ब्लॉक को कैसे मुक्त किया जाए, अंतर्निहित मॉलोक/फ्री (जो नया/हटाएं/नया []/हटाएं [] आम तौर पर कॉल करें) हमेशा याद न करें वास्तव में आप कितनी मेमोरी मांगते हैं, यह गोलाकार हो सकता है (उदाहरण के लिए, एक बार जब आप 4K से ऊपर हो जाते हैं तो इसे अक्सर अगले 4 के आकार के ब्लॉक तक गोल किया जाता है)।

इसलिए, अगर मेमोरी ब्लॉक का आकार भी मिल सकता है, तो यह हमें नहीं बताता है कि नई [] ed मेमोरी में कितने मूल्य हैं, क्योंकि यह छोटा हो सकता है। इसलिए, हमें एक अतिरिक्त पूर्णांक स्टोर करना होगा जो हमें बता रहा है कि कितने मूल्य हैं।

EXCEPT, अगर निर्माण के प्रकार में कोई विनाशक नहीं है, तो हटाएं [] को मेमोरी ब्लॉक को छोड़कर कुछ भी करने की ज़रूरत नहीं है, और इसलिए कुछ भी स्टोर नहीं करना है!

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