मॉलोक () और मुफ्त () कैसे काम करते हैं?


276

मैं जानना चाहता हूं कि कैसे mallocऔर कैसे freeकाम करते हैं।

int main() {
    unsigned char *p = (unsigned char*)malloc(4*sizeof(unsigned char));
    memset(p,0,4);
    strcpy((char*)p,"abcdabcd"); // **deliberately storing 8bytes**
    cout << p;
    free(p); // Obvious Crash, but I need how it works and why crash.
    cout << p;
    return 0;
}

अगर यह संभव है तो स्मृति स्तर पर गहराई से जवाब देने पर मैं वास्तव में आभारी रहूंगा।


5
क्या यह वास्तव में संकलक और रनटाइम लाइब्रेरी पर निर्भर नहीं होना चाहिए?
विल्क्स-

9
यह सीआरटी कार्यान्वयन पर निर्भर करेगा। इसलिए आप इसे सामान्य नहीं कर सकते।
नवीन

58
यह स्ट्रैची 9 बाइट्स लिखता है, 8. नहीं। पूर्ण टर्मिनेटर मत भूलना ;-)।
इवान टेरान


2
@ LưuV LnhPhúc वह C ++ है। ध्यान देंcout <<
ब्रैडेन बेस्ट

जवाबों:


385

ठीक है कि मॉलॉक के बारे में कुछ जवाब पहले से ही पोस्ट किए गए थे।

अधिक दिलचस्प हिस्सा यह है कि कैसे निशुल्क काम करता है (और इस दिशा में, मॉलोक भी बेहतर समझा जा सकता है)।

कई मॉलॉक / नि: शुल्क कार्यान्वयन में, फ्री आमतौर पर मेमोरी को ऑपरेटिंग सिस्टम (या कम से कम केवल दुर्लभ मामलों में) में वापस नहीं करता है। कारण यह है कि आप अपने ढेर में अंतराल प्राप्त करेंगे और इस प्रकार यह हो सकता है, कि आप अपने 2 या 4 जीबी वर्चुअल मेमोरी को अंतराल के साथ समाप्त कर दें। इससे बचना चाहिए, क्योंकि जैसे ही वर्चुअल मेमोरी खत्म होगी, आप वास्तव में बड़ी परेशानी में पड़ जाएंगे। दूसरा कारण यह है, कि ओएस केवल मेमोरी चंक्स को संभाल सकता है जो एक विशिष्ट आकार और संरेखण के होते हैं। विशिष्ट होने के लिए: आम तौर पर ओएस केवल उन ब्लॉकों को संभाल सकता है जो वर्चुअल मेमोरी मैनेजर संभाल सकता है (सबसे अक्सर 512 बाइट्स के गुणक जैसे 4KB)।

तो ओएस को 40 बाइट्स वापस करना सिर्फ काम नहीं करेगा। तो मुफ्त में क्या करता है?

फ्री मेमोरी ब्लॉक को अपनी खुद की फ्री ब्लॉक सूची में रखेगा। आम तौर पर यह पता स्थान में आसन्न ब्लॉकों को एक साथ पिघलाने की भी कोशिश करता है। मुक्त ब्लॉक सूची मेमोरी चंक्स की सिर्फ एक गोलाकार सूची है जिसमें शुरुआत में कुछ प्रशासनिक डेटा होते हैं। यही कारण है कि मानक मॉलोक / मुक्त के साथ बहुत छोटे स्मृति तत्वों का प्रबंधन कुशल नहीं है। प्रत्येक मेमोरी चंक को अतिरिक्त डेटा की आवश्यकता होती है और छोटे आकार के साथ अधिक विखंडन होता है।

फ्री-लिस्ट भी पहली जगह है जो मैलोडोक को तब दिखती है जब मेमोरी के एक नए हिस्से की जरूरत होती है। ओएस से नई मेमोरी के लिए कॉल करने से पहले इसे स्कैन किया जाता है। जब एक हिस्सा पाया जाता है जो आवश्यक मेमोरी से बड़ा होता है, तो इसे दो भागों में विभाजित किया जाता है। एक को फोन करने वाले को लौटा दिया जाता है, दूसरे को मुफ्त सूची में डाल दिया जाता है।

इस मानक व्यवहार के लिए कई अलग-अलग अनुकूलन हैं (उदाहरण के लिए स्मृति की छोटी मात्रा के लिए)। लेकिन चूंकि मॉलोक और फ्री इतना सार्वभौमिक होना चाहिए, मानक व्यवहार हमेशा कमबैक होता है जब विकल्प उपयोग करने योग्य नहीं होते हैं। मुक्त-सूची को संभालने में भी अनुकूलन हैं - उदाहरण के लिए आकारों द्वारा क्रमबद्ध सूचियों में विखंडन को संग्रहीत करना। लेकिन सभी अनुकूलन की अपनी सीमाएँ भी हैं।

आपका कोड क्रैश क्यों होता है:

इसका कारण यह है कि 4 वर्णों के क्षेत्र के आकार में 9 वर्ण (अनुगामी नल बाइट को न भूलें) लिखकर, आप संभवतः स्मृति के एक अन्य भाग के लिए संग्रहीत प्रशासनिक-डेटा को अधिलेखित कर देंगे जो आपके डेटा के "पीछे" रहता है। चूँकि यह डेटा अक्सर मेमोरी चंक्स के "सामने" में संग्रहित होता है। जब नि: शुल्क तब अपने चंक को मुफ्त सूची में डालने की कोशिश करता है, तो यह इस प्रशासनिक-डेटा को छू सकता है और इसलिए एक अधिलेखित सूचक पर ठोकर खा सकता है। इससे सिस्टम क्रैश हो जाएगा।

यह एक बल्कि सुंदर व्यवहार है। मैंने उन स्थितियों को भी देखा है जहां एक भगोड़ा सूचक ने मेमोरी-फ्री-लिस्ट में डेटा को ओवरराइट कर दिया है और सिस्टम तुरंत दुर्घटनाग्रस्त नहीं हुआ, लेकिन बाद में कुछ सबरूटीन्स। मध्यम जटिलता की एक प्रणाली में भी ऐसी समस्याएं वास्तव में हो सकती हैं, वास्तव में डिबग करना कठिन है! जिस एक मामले में मैं शामिल था, उसे दुर्घटना के कारण का पता लगाने में हमें (डेवलपर्स का एक बड़ा समूह) कई दिन लगे - क्योंकि यह मेमोरी डंप द्वारा बताए गए स्थान से बिल्कुल अलग स्थान पर था। यह टाइम-बम की तरह है। तुम्हें पता है, आपका अगला "मुक्त" या "मॉलॉक" दुर्घटनाग्रस्त हो जाएगा, लेकिन आप नहीं जानते कि क्यों!

वे कुछ सबसे खराब C / C ++ समस्याएं हैं, और एक कारण है कि पॉइंटर्स इतनी समस्याग्रस्त हो सकते हैं।


62
कई लोगों को यह पता ही नहीं है कि मुफ्त () ओएस को मेमोरी वापस नहीं किया जा सकता है, यह बहुत बुरा है। उन्हें प्रबुद्ध करने में मदद के लिए धन्यवाद।
आर्टेलियस सेप

आर्टेलियस: इसके विपरीत, नया हमेशा करेगा?
गुइल्यूम .07

3
@ Guillaume07 मुझे लगता है कि आप हटाना चाहते थे, नया नहीं। नहीं, यह (आवश्यक) नहीं है। डिलीट और फ्री डू (लगभग) एक ही चीज़। यहाँ MSVC2013 में हर एक को कॉल किया गया है: goo.gl/3O2Kyu
Yay295

1
नष्ट हमेशा विध्वंसक कहेंगे, लेकिन स्मृति बाद में आवंटन के लिए एक मुफ्त सूची में जा सकती है। कार्यान्वयन के आधार पर, यह वही नि: शुल्क सूची भी हो सकती है जिसका उपयोग मॉलोक करता है।
डेविड सी।

1
@Juergen लेकिन जब मुफ़्त () अतिरिक्त बाइट पढ़ते हैं जिसमें जानकारी होती है कि मॉलोक से कितनी मेमोरी आवंटित की गई है, तो यह 4. प्राप्त होता है। फिर दुर्घटना कैसे हुई या कैसे मुक्त () प्रशासनिक डेटा को स्पर्श करें?
अपरिभाषित व्यवहार

56

जैसा कि एलसर इस फोरम थ्रेड में कहते हैं :

आपकी प्रक्रिया में स्मृति का एक क्षेत्र है, पता x से पता y तक, ढेर कहा जाता है। आपके सभी मॉलोकैड डेटा इस क्षेत्र में रहते हैं। मॉलोक () कुछ डेटा संरचना रखता है, आइए एक सूची कहते हैं, ढेर में अंतरिक्ष के सभी मुक्त विखंडन की। जब आप मॉलॉक कहते हैं, तो यह सूची के माध्यम से दिखता है जो आपके लिए काफी बड़ा है, इसके लिए एक संकेतक लौटाता है, और इस तथ्य को दर्ज करता है कि यह किसी भी अधिक मुक्त नहीं है और यह कितना बड़ा है। जब आप एक ही पॉइंटर से फ्री () कॉल करते हैं, तो फ्री () दिखता है कि चंक कितना बड़ा है और इसे फ्री चंक्स की सूची में वापस जोड़ता है ()। यदि आप malloc () कहते हैं और यह ढेर में कोई भी बड़ा हिस्सा नहीं मिल सकता है, तो यह ढेर को बढ़ाने के लिए brk () syscall का उपयोग करता है, अर्थात एड्रेस y को बढ़ाएं और पुराने y और नए y के बीच के सभी पते का कारण बनें वैध स्मृति हो। brk () एक syscall होना चाहिए;

मॉलॉक () सिस्टम / कंपाइलर पर निर्भर है इसलिए एक विशिष्ट उत्तर देना मुश्किल है। मूल रूप से हालांकि यह इस बात का ट्रैक रखता है कि यह किस मेमोरी को आबंटित किया गया है और यह निर्भर करता है कि यह आपके कॉल को मुफ्त में कैसे विफल या सफल हो सकता है।

malloc() and free() don't work the same way on every O/S.


1
यही कारण है कि इसे अपरिभाषित व्यवहार कहा जाता है। जब आप एक अवैध लेखन के बाद मुफ्त कॉल करते हैं तो एक कार्यान्वयन आपके नाक से राक्षसों को बाहर निकाल सकता है। आपको कभी नहीं जानते।
ब्रैडेन बेस्ट

35

मल्लोक का एक कार्यान्वयन / नि: शुल्क निम्नलिखित करता है:

  1. ओएस से sbrk () (यूनिक्स कॉल) के माध्यम से मेमोरी का एक ब्लॉक प्राप्त करें।
  2. मेमोरी के उस ब्लॉक के चारों ओर एक हेडर और एक पाद बनाएँ, जैसे कि आकार, अनुमतियाँ और अगले और पिछले ब्लॉक जैसी कुछ जानकारी।
  3. जब मॉलॉक में कॉल आता है, तो एक सूची संदर्भित की जाती है जो उचित आकार के ब्लॉक की ओर इशारा करती है।
  4. इस ब्लॉक को फिर लौटाया जाता है और हेडर और फूटर उसी के अनुसार अपडेट किए जाते हैं।

25

मेमोरी प्रोटेक्शन में पेज-ग्रैन्युलैरिटी है और इसके लिए कर्नेल इंटरैक्शन की आवश्यकता होगी

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

मेमोरी केवल आपके प्रोग्राम से पृष्ठों की इकाइयों में निकाली जा सकती है, और यहां तक ​​कि इसका अवलोकन किए जाने की संभावना नहीं है।

कॉलोक (3) और मॉलॉक (3) मेमोरी को पाने के लिए कर्नेल के साथ इंटरैक्ट करते हैं, यदि आवश्यक हो। लेकिन मुफ्त के अधिकांश कार्यान्वयन (3) कर्नेल 1 में मेमोरी वापस नहीं करते हैं , वे इसे केवल एक मुक्त सूची में जोड़ते हैं जो कॉलोक () और मॉलोक () बाद में जारी किए गए ब्लॉकों का पुन: उपयोग करने के लिए परामर्श करेगा।

यहां तक ​​कि अगर एक मुफ़्त () सिस्टम को मेमोरी वापस करना चाहता था, तो उसे वास्तव में इस क्षेत्र की रक्षा करने के लिए कर्नेल प्राप्त करने के लिए कम से कम एक सन्निहित मेमोरी पेज की आवश्यकता होगी, इसलिए एक छोटे ब्लॉक को जारी करने से केवल सुरक्षा परिवर्तन हो सकता है यदि यह था पिछले एक पेज में छोटे ब्लॉक।

तो आपका ब्लॉक वहाँ है, मुफ्त सूची पर बैठे। आप लगभग हमेशा इसे और पास की स्मृति तक पहुंच सकते हैं जैसे कि यह अभी भी आवंटित किया गया था। सी सीधे मशीन कोड के लिए संकलित करता है और विशेष डिबगिंग व्यवस्था के बिना लोड और स्टोर पर कोई संन्यास की जांच नहीं होती है। अब, यदि आप एक निशुल्क ब्लॉक की कोशिश करते हैं और एक्सेस करते हैं, तो लाइब्रेरी कार्यान्वयनकर्ताओं पर अनुचित मांग नहीं करने के लिए मानक द्वारा व्यवहार अपरिभाषित है। यदि आप आवंटित किए गए ब्लॉक के बाहर मुक्त मेमोरी या मेयोरी तक पहुंचने का प्रयास करते हैं, तो कई चीजें हैं जो गलत हो सकती हैं:

  • कभी-कभी आवंटनकर्ता मेमोरी के अलग-अलग ब्लॉक बनाए रखते हैं, कभी-कभी वे आपके ब्लॉक के ठीक पहले या बाद में आवंटित हेडर का उपयोग करते हैं, मुझे लगता है कि आपके ब्लॉक का अनुमान है, लेकिन वे मुफ्त सूची रखने के उद्देश्य से ब्लॉक के भीतर मेमोरी का उपयोग करना चाहते हैं। आपस मे जुड़े हैं। यदि ऐसा है, तो आपका पढ़ना ब्लॉक ठीक है, लेकिन इसकी सामग्री बदल सकती है, और ब्लॉक को लिखने से आवंटनकर्ता को दुर्व्यवहार या दुर्घटना की संभावना होगी।
  • स्वाभाविक रूप से, आपके ब्लॉक को भविष्य में आवंटित किया जा सकता है, और फिर इसे आपके कोड या लाइब्रेरी रूटीन या कॉलोक () द्वारा शून्य के साथ अधिलेखित किए जाने की संभावना है।
  • यदि ब्लॉक को फिर से जोड़ा जाता है, तो इसका आकार भी बदल सकता है, जिस स्थिति में विभिन्न स्थानों में अभी भी अधिक लिंक या आरंभीकरण लिखा जाएगा।
  • जाहिर है कि आप इस सीमा से इतनी दूर संदर्भ दे सकते हैं कि आप अपने किसी प्रोग्राम के कर्नेल-ज्ञात सेगमेंट की सीमा पार कर लें, और इस एक मामले में आप फंस जाएंगे।

संचालन का सिद्धांत

इसलिए, अपने उदाहरण से समग्र सिद्धांत पर पीछे की ओर काम करते हुए, मॉलॉक (3) को कर्नेल से मेमोरी की आवश्यकता होती है जब उसे इसकी आवश्यकता होती है, और आमतौर पर पृष्ठों की इकाइयों में। कार्यक्रम की आवश्यकता के अनुसार इन पृष्ठों को विभाजित या समेकित किया जाता है। Malloc और नि: शुल्क सहयोग एक निर्देशिका बनाए रखने के लिए। वे बड़े ब्लॉक प्रदान करने में सक्षम होने के लिए आसन्न मुक्त ब्लॉक समेटते हैं। निर्देशिका लिंक की गई सूची बनाने के लिए मुक्त ब्लॉकों में मेमोरी का उपयोग कर सकती है या नहीं भी कर सकती है। (विकल्प थोड़ा अधिक साझा-मेमोरी और पेजिंग-फ्रेंडली है, और इसमें विशेष रूप से डायरेक्टरी के लिए मेमोरी आवंटित करना शामिल है।) विशेष और वैकल्पिक डिबगिंग कोड को संकलित करने पर भी किसी ब्लॉक की पहुंच को लागू करने की क्षमता होने पर मलोक और फ्री में बहुत कम है। कार्यक्रम।


1. तथ्य यह है कि सिस्टम को मेमोरी वापस करने का प्रयास करने के लिए मुफ्त () प्रयास के बहुत कम कार्यान्वयन जरूरी नहीं है कि कार्यान्वयनकर्ताओं के बंद होने के कारण। केवल कोड को निष्पादित करने की तुलना में कर्नेल के साथ बातचीत बहुत धीमी है, और लाभ छोटा होगा। अधिकांश कार्यक्रमों में एक स्थिर-स्थिति या बढ़ती स्मृति पदचिह्न होते हैं, इसलिए समय व्यतीत करने योग्य स्मृति की तलाश करने वाले ढेर का विश्लेषण करने में बिताया गया समय पूरी तरह से बर्बाद हो जाएगा। अन्य कारणों में इस तथ्य को शामिल किया गया है कि आंतरिक विखंडन पृष्ठ-संरेखित ब्लॉकों को मौजूद होने की संभावना नहीं बनाता है, और यह संभावना है कि एक खंड को वापस करने से दोनों तरफ खंड खंड हो जाएंगे। अंत में, कुछ प्रोग्राम जो बड़ी मात्रा में मेमोरी वापस करते हैं, वे मॉलोक () को बायपास करने की संभावना रखते हैं और बस वैसे भी आवंटित और निशुल्क पृष्ठों को आवंटित करते हैं।


अच्छा उत्तर। पेपर की सिफारिश करेंगे: डायनेमिक स्टोरेज एलोकेशन: विल्सन वगैरह द्वारा आंतरिक मैकेनिज्म पर गहन समीक्षा, जैसे हेडर फील्ड और फ्री लिस्ट, जो कि एलाटेटर द्वारा उपयोग किए जाते हैं, के लिए एक सर्वेक्षण और महत्वपूर्ण समीक्षा।
गोएलेर ४४४

23

सिद्धांत रूप में, इस एप्लिकेशन के लिए मॉलोक को ऑपरेटिंग सिस्टम से मेमोरी मिलती है। हालाँकि, जब से आप केवल 4 बाइट्स चाहते हैं, और OS को पृष्ठों (अक्सर 4k) में काम करने की आवश्यकता होती है, उसके लिए मॉलोक थोड़ा अधिक करता है। यह एक पेज लेता है, और इसमें अपनी जानकारी डालता है ताकि यह आपके द्वारा आवंटित किए गए और उस पेज से मुक्त हो सके।

जब आप 4 बाइट्स आवंटित करते हैं, उदाहरण के लिए, मॉलोक आपको 4 बाइट्स के लिए एक पॉइंटर देता है। आप जो महसूस नहीं कर सकते हैं वह यह है कि आपके 4 बाइट्स से पहले 8-12 बाइट्स का उपयोग मॉलोक द्वारा आपके द्वारा आवंटित सभी मेमोरी की एक श्रृंखला बनाने के लिए किया जा रहा है। जब आप फ्री कॉल करते हैं, तो यह आपके पॉइंटर को ले जाता है, यह डेटा कहां है, और उसी पर काम करता है।

जब आप फ्री मेमोरी देते हैं, तो मॉलॉक उस मेमोरी को चेन से ब्लॉक कर देता है ... और उस मेमोरी को ऑपरेटिंग सिस्टम पर वापस कर सकता है या नहीं। यदि ऐसा होता है, तो उस मेमोरी तक पहुंच संभवत: विफल हो जाएगी, क्योंकि ओएस उस स्थान तक पहुंचने के लिए आपकी अनुमतियां ले लेगा। यदि मॉलोक मेमोरी रखता है (क्योंकि इसमें उस पृष्ठ में, या कुछ अनुकूलन के लिए आवंटित अन्य चीजें हैं), तो काम करने के लिए पहुंच होगी। यह अभी भी गलत है, लेकिन यह काम कर सकता है।

अस्वीकरण: मैंने जो वर्णन किया है वह मॉलोक का एक सामान्य कार्यान्वयन है, लेकिन किसी भी तरह से संभव नहीं है।


12

NUL टर्मिनेटर के कारण आपकी स्ट्रैची लाइन 9 बाइट्स, 8 नहीं, 8 स्टोर करने का प्रयास करती है। यह अपरिभाषित व्यवहार को आमंत्रित करता है।

मुफ्त में कॉल क्रैश हो सकता है या नहीं। आपके आवंटन के 4 बाइट्स के बाद "मेमोरी" का उपयोग आपके C या C ++ कार्यान्वयन के लिए कुछ और के लिए किया जा सकता है। अगर इसका इस्तेमाल किसी और चीज के लिए किया जाता है, तो यह सब खत्म हो जाने के कारण यह होगा कि "कुछ और" गलत हो जाएगा, लेकिन अगर इसे किसी और चीज के लिए इस्तेमाल नहीं किया जाता है, तो आप इसके साथ दूर हो सकते हैं। "इसके साथ भाग जाना" अच्छा लग सकता है, लेकिन वास्तव में बुरा है, क्योंकि इसका मतलब है कि आपका कोड ओके को चलाने के लिए दिखाई देगा, लेकिन भविष्य के रन पर आप इसके साथ दूर नहीं हो सकते।

डिबगिंग-शैली मेमोरी एलोकेटर के साथ, आप पा सकते हैं कि एक विशेष गार्ड मूल्य वहाँ लिखा गया है, और उस मूल्य और पैनिक के लिए मुफ्त चेक अगर यह नहीं मिलता है।

अन्यथा, आप पा सकते हैं कि अगले 5 बाइट्स में मेमोरी के कुछ अन्य ब्लॉक से संबंधित लिंक नोड का हिस्सा शामिल है जिसे अभी तक आवंटित नहीं किया गया है। अपने ब्लॉक को मुक्त करना इसे उपलब्ध ब्लॉकों की सूची में शामिल करना अच्छी तरह से शामिल कर सकता है, और क्योंकि आपने सूची नोड में स्क्रिबल कर दिया है, तो यह ऑपरेशन एक अमान्य मूल्य के साथ एक पॉइंटर को रोक सकता है, जिससे दुर्घटना हो सकती है।

यह सब मेमोरी एलोकेटर पर निर्भर करता है - विभिन्न कार्यान्वयन अलग-अलग तंत्र का उपयोग करते हैं।


12

मॉलोक () और मुफ्त () कैसे काम करता है यह रनटाइम लाइब्रेरी पर निर्भर करता है। आम तौर पर, मॉलोक () ऑपरेटिंग सिस्टम से एक ढेर (मेमोरी का एक ब्लॉक) आवंटित करता है। मॉलॉक () के लिए प्रत्येक अनुरोध तब इस मेमोरी का एक छोटा हिस्सा आवंटित करता है जो कॉलर को एक सूचक लौटाता है। स्मृति आबंटन रूटीन को मेमोरी के ब्लॉक के बारे में कुछ अतिरिक्त जानकारी संग्रहीत करनी होगी जो कि उपयोग किए गए और मुफ्त मेमोरी को ट्रैक पर रखने में सक्षम हो। यह जानकारी अक्सर कुछ बाइट्स में संग्रहीत की जाती है, इससे पहले कि पॉलीस्टर मॉलोक () द्वारा वापस आ जाए और यह मेमोरी ब्लॉकों की एक लिंक की गई सूची हो सकती है।

मैलोडोक () द्वारा आवंटित मेमोरी के ब्लॉक को अतीत में लिखने से आप संभवतः अगले ब्लॉक के कुछ बुक-कीपिंग जानकारी को नष्ट कर देंगे जो कि मेमोरी का शेष अप्रयुक्त ब्लॉक हो सकता है।

एक जगह जहां आप प्रोग्राम भी क्रैश कर सकते हैं, बफर में बहुत सारे अक्षरों की नकल करते समय। यदि अतिरिक्त वर्ण ढेर के बाहर स्थित हैं, तो आपको एक्सेस उल्लंघन मिल सकता है क्योंकि आप गैर-मौजूदा मेमोरी में लिखने की कोशिश कर रहे हैं।


6

यह विशेष रूप से मॉलोक और मुफ्त के साथ कुछ नहीं करना है। आपका प्रोग्राम स्ट्रिंग की प्रतिलिपि बनाने के बाद अपरिभाषित व्यवहार प्रदर्शित करता है - यह उस बिंदु पर या उसके बाद किसी भी बिंदु पर दुर्घटनाग्रस्त हो सकता है। यह तब भी सच होगा जब आप कभी भी मॉलॉक और फ्री का इस्तेमाल नहीं करते हैं, और स्टैक या स्टैटिकली पर चार्ट को आवंटित करते हैं।


5

मॉलॉक और मुक्त कार्यान्वयन निर्भर हैं। एक विशिष्ट कार्यान्वयन में उपलब्ध मेमोरी को "मुक्त सूची" में विभाजित करना शामिल है - उपलब्ध मेमोरी ब्लॉकों की एक लिंक की गई सूची। कई कार्यान्वयन कृत्रिम रूप से इसे छोटी बनाम बड़ी वस्तुओं में विभाजित करते हैं। फ्री ब्लॉक की शुरुआत इस बात से होती है कि मेमोरी ब्लॉक कितना बड़ा है और अगला कहां है आदि।

जब आप मॉलॉक करते हैं, तो एक ब्लॉक को मुफ्त सूची से निकाला जाता है। जब आप मुक्त होते हैं, तो ब्लॉक को मुफ्त सूची में वापस रखा जाता है। संभावना है, जब आप अपने पॉइंटर के अंत को ओवरराइट करते हैं, तो आप निशुल्क सूची में एक ब्लॉक के हेडर पर लिख रहे हैं। जब आप अपनी मेमोरी को मुक्त करते हैं, तो फ्री () अगले ब्लॉक को देखने की कोशिश करता है और संभवत: एक पॉइंटर को हिट करने का कारण बनता है जो एक बस त्रुटि का कारण बनता है।


4

वैसे यह मेमोरी एलोकेटर कार्यान्वयन और ओएस पर निर्भर करता है।

उदाहरण के लिए विंडोज़ के तहत एक प्रक्रिया एक पेज या अधिक रैम के लिए पूछ सकती है। OS फिर उन पेज को प्रोसेस में असाइन करता है। हालाँकि, यह आपके अनुप्रयोग के लिए आवंटित स्मृति नहीं है। CRT मेमोरी एलोकेटर मेमोरी को एक सन्निहित "उपलब्ध" ब्लॉक के रूप में चिह्नित करेगा। CRT मेमोरी एलोकेटर तब मुफ्त ब्लॉक की सूची के माध्यम से चलेगा और सबसे छोटे संभव ब्लॉक को खोज सकता है जो इसका उपयोग कर सकते हैं। इसके बाद इसे उस ब्लॉक का अधिक से अधिक हिस्सा लेना होगा, जिसकी उसे आवश्यकता है और इसे "आवंटित" सूची में जोड़ा जाएगा। वास्तविक मेमोरी आवंटन के प्रमुख से संलग्न एक हेडर होगा। इस शीर्ष लेख में विभिन्न बिट जानकारी होगी (उदाहरण के लिए, लिंक की गई सूची बनाने के लिए अगले और पिछले आबंटित ब्लॉक शामिल हो सकते हैं। इसमें अधिकतर आवंटन का आकार होगा)।

फ्री फिर हेडर को हटा देगा और इसे फ्री मेमोरी लिस्ट में वापस जोड़ देगा। यदि यह आसपास के मुक्त ब्लॉक के साथ एक बड़ा ब्लॉक बनाता है तो इन्हें एक बड़ा ब्लॉक देने के लिए एक साथ जोड़ा जाएगा। यदि एक पूरा पृष्ठ अब आबंटक मुक्त हो जाएगा, तो सबसे अधिक संभावना है, पृष्ठ को ओएस पर लौटा दें।

यह कोई साधारण समस्या नहीं है। OS एलोकेटर भाग पूरी तरह से आपके नियंत्रण से बाहर है। मैं आपको डग ले के मल्लोक (DLMalloc) जैसे कुछ के माध्यम से पढ़ने की सलाह देता हूं कि यह समझने के लिए कि एक काफी तेजी से आवंटन कैसे काम करेगा।

संपादित करें: आपका क्रैश इस तथ्य के कारण होगा कि आवंटन से बड़ा लिखकर आपने अगले मेमोरी हेडर को अधिलेखित कर दिया है। इस तरह जब यह मुक्त हो जाता है तो यह बहुत भ्रमित हो जाता है कि यह वास्तव में क्या है और यह निम्नलिखित ब्लॉक में विलय कैसे किया जाता है। यह हमेशा मुफ्त में सीधे दुर्घटना का कारण नहीं हो सकता है। यह आगे चलकर दुर्घटना का कारण बन सकता है। सामान्य रूप से मेमोरी ओवरराइट से बचें!


3

आपका प्रोग्राम क्रैश हो जाता है क्योंकि इसमें ऐसी मेमोरी का उपयोग किया गया है जो आपकी नहीं है। इसका उपयोग किसी और के द्वारा किया जा सकता है या नहीं - यदि आप भाग्यशाली हैं तो आप दुर्घटनाग्रस्त हो जाते हैं, यदि नहीं तो समस्या लंबे समय तक छिपी रह सकती है और बाद में आकर आपको काट सकती है।

जहां तक ​​मैलोका / मुक्त कार्यान्वयन जाता है - संपूर्ण पुस्तकें विषय के लिए समर्पित हैं। मूल रूप से आवंटनकर्ता को ओएस से मेमोरी का बड़ा हिस्सा मिलेगा और उन्हें आपके लिए प्रबंधित किया जाएगा। एक आवंटनकर्ता को जिन समस्याओं का समाधान करना चाहिए उनमें से कुछ हैं:

  • नई मेमोरी कैसे प्राप्त करें
  • इसे कैसे स्टोर करें - (सूची या अन्य संरचना, विभिन्न आकारों की मेमोरी चंक्स के लिए कई सूचियाँ, और इसी तरह)
  • यदि उपयोगकर्ता वर्तमान में उपलब्ध की तुलना में अधिक मेमोरी का अनुरोध करता है तो क्या करें (OS से अधिक मेमोरी का अनुरोध करें, कुछ मौजूदा ब्लॉकों में शामिल हों, उन्हें वास्तव में कैसे जुड़ें, ...)
  • जब उपयोगकर्ता स्मृति मुक्त करता है तो क्या करें
  • डिबग आबंटक आपको बड़ा हिस्सा दे सकते हैं, जिसे आपने अनुरोध किया था और इसे कुछ बाइट पैटर्न से भर दिया था, जब आप मेमोरी को मुक्त करते हैं, तो यह जांच सकते हैं कि ब्लॉक के बाहर लिखा हुआ है (जो आपके मामले में हो रहा है) ...

2

यह कहना कठिन है क्योंकि वास्तविक व्यवहार अलग-अलग संकलक / रनटाइम के बीच भिन्न होता है। यहां तक ​​कि डिबग / रिलीज बिल्ड का अलग व्यवहार है। VS2005 का डिबग बिल्ड मेमोरी भ्रष्टाचार का पता लगाने के लिए आवंटन के बीच मार्करों को सम्मिलित करेगा, इसलिए एक दुर्घटना के बजाय, यह मुफ्त में जोर देगा ()।


1

यह महसूस करना भी महत्वपूर्ण है कि बस प्रोग्राम ब्रेक पॉइंटर को चारों ओर ले जाने brkऔर sbrkवास्तव में मेमोरी को आवंटित नहीं करने के लिए, यह सिर्फ पता स्थान सेट करता है। लिनक्स पर, उदाहरण के लिए, मेमोरी को वास्तविक भौतिक पृष्ठों द्वारा "समर्थित" किया जाएगा, जब उस पते की सीमा तक पहुंच हो, जिसके परिणामस्वरूप पृष्ठ दोष होगा, और अंततः पृष्ठ आवंटन में कर्नेल को कॉल करने के लिए एक बैकिंग पेज मिलेगा।

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