ऑपरेंड ऐरे के आकार को [] "पता" कैसे हटाता है?


250
Foo* set = new Foo[100];
// ...
delete [] set;

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


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

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

जवाबों:


181

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


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

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

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

33
क्षमा करें, लेकिन यह उत्तर बिंदु को याद करता है। क्वांटमपेट का जो वर्णन किया गया है, वह मूल रूप से "कैसे freeजानता है कि मेमोरी को कितना कम करना है"। हां, मेमोरी ब्लॉक का आकार "कहीं न कहीं" malloc(सामान्य रूप से ब्लॉक में) संग्रहीत होता है, इसलिए यह freeपता है कि कैसे । हालाँकि, new[]/ delete[]एक अलग कहानी है। उत्तरार्द्ध मूल रूप से malloc/ के शीर्ष पर काम करते हैं freenew[]यह मेमोरी ब्लॉक (स्वतंत्र रूप से malloc) में बनाए गए तत्वों की संख्या को भी संग्रहीत करता है , ताकि बाद में delete[]उस संख्या को पुनः प्राप्त कर सकें और उचित संख्या में विध्वंसक कॉल कर सकें ।
चींटी

26
यानी शारीरिक रूप से दो काउंटरों को ब्लॉक में संग्रहीत किया जाता है: ब्लॉक आकार (द्वारा malloc) और तत्व गणना (द्वारा new[])। ध्यान दें, पूर्व का उपयोग बाद की गणना करने के लिए नहीं किया जा सकता है, क्योंकि सामान्य स्थिति में मेमोरी ब्लॉक का आकार अनुरोधित आकार की सरणी के लिए वास्तव में आवश्यक से बड़ा हो सकता है। यह भी ध्यान दें कि सरणी तत्व काउंटर केवल गैर-तुच्छ विध्वंसक प्रकार के लिए आवश्यक है। तुच्छ विध्वंसक के साथ प्रकारों के लिए काउंटर द्वारा संग्रहीत नहीं किया जाता है new[]और निश्चित रूप से, द्वारा पुनर्प्राप्त नहीं किया जाता है delete[]
२४'०

23

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

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

यहाँ

int* i = new int[4];

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

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

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

*temp = 4;

और सेट करें i

i = temp + 1;

तो i5 नहीं, 4 तत्वों की एक सरणी को इंगित करेगा।

और विलोपन

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)

9

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

इसके अलावा आपको नई [] के साथ मेमोरी आवंटित करने पर डिलीट [] का उपयोग करना चाहिए, क्योंकि डिलीट का ऐरे संस्करण जानता है कि (और कहां) इसे सही मात्रा में मेमोरी को खाली करने की जरूरत है - और उचित संख्या में डिस्ट्रक्टर्स को कॉल करें वस्तुओं के लिए।


5

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

[जानकारी] [मेम आप के लिए पूछा ...]

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

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


4

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


3

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

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

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

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


2

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


0

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

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


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

0

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

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

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.