2010-09-10 8 views
11

realloc गतिशील रूप से स्मृति को पुन: आवंटित करने के लिए उपयोग किया जाता है।स्मृति की अनुक्रमिक जगह नहीं होने पर पुनर्विक्रय क्या होगा?

मान लीजिए मैं malloc समारोह का उपयोग कर 7 बाइट्स आवंटित है और अब मैं इसे 30 बाइट्स का विस्तार करना चाहते हैं।

पृष्ठभूमि में क्या होगा अगर कोई अनुक्रमिक स्मृति में 30 बाइट्स के स्थान (लगातार एक ही पंक्ति में) क्या है?

कोई त्रुटि या इच्छा स्मृति भागों में आवंटित किया वहाँ है?

उत्तर

11

realloc पर्दे के पीछे काम करता है मोटे तौर पर इस तरह:

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

तो, आप NULL के लिए परीक्षण द्वारा विफलता के लिए परीक्षण कर सकते हैं, लेकिन ध्यान रखें कि आप पुराने सूचक बहुत जल्दी ऊपर लिख नहीं करते:

int* p = malloc(x); 
/* ... */ 
p = realloc(p, y); /* WRONG: Old pointer lost if realloc fails: memory leak! */ 
/* Correct way: */ 
{ 
    int* temp = realloc(p, y); 
    if (NULL == temp) 
    { 
    /* Handle error; p is still valid */ 
    } 
    else 
    { 
    /* p now possibly points to deallocated memory. Overwrite it with the pointer 
     to the new block, to start using that */ 
    p = temp; 
    } 
} 
+0

क्या यह सभी कार्यान्वयन के लिए 'realloc' काम करता है? –

+0

@CoolGuy: कुछ कार्यान्वयन मौजूदा ब्लॉक को विस्तारित करने के पहले चरण को करने में सक्षम नहीं हो सकते हैं, लेकिन अन्यथा यह सभी कार्यान्वयन के लिए 'realloc' का अवलोकन योग्य व्यवहार है। –

1

man page से:

realloc() नव आबंटित स्मृति है, जो उपयुक्त रूप चर के किसी भी प्रकार के लिए गठबंधन और ptr से अलग हो सकता है, या यदि शून्य करने के लिए एक सूचक रिटर्न अनुरोध विफल रहता है।

तो दूसरे शब्दों में, विफलता का पता लगाने के लिए, जांच करें कि परिणाम नल था या नहीं।

संपादित करें: के रूप में टिप्पणी में बताया गया है, अगर कॉल विफलताओं, मूल स्मृति मुक्त नहीं है।

+2

मैन पेज से नोट करने के लिए उपयुक्त: यदि realloc() विफल रहता है तो मूल ब्लॉक को छूटा नहीं जाता है; यह मुक्त या स्थानांतरित नहीं है। –

6

realloc केवल सफल होने अगर यह एक सन्निहित ("अनुक्रमिक" अपने शब्दों में) स्मृति के ब्लॉक लौट सकते हैं होगा। यदि ऐसा कोई ब्लॉक मौजूद नहीं है, तो यह NULL वापस आ जाएगा।

+4

@ मार्क - मूल मेमोरी अपरिवर्तित बनी हुई है। इस संदर्भ में एक आम बग 'x = realloc (x)' है - आपको त्रुटि पर मूल x को लीक करने से बचने के लिए 'newX = realloc (x)' करना होगा। –

+0

@ स्टेव टाउनसेंड - केवल तभी होता है जब यह संस्कार में विफल रहता है? सफल होने पर यह मूल सूचक को मुक्त करता है। और इस पृष्ठ में कौन मार्क? O_o –

+0

मुझे लगता है कि एक त्रुटि हुई थी। पहली टिप्पणी उपयोगकर्ता sharptooth से दिखाया गया था और अब यह बदल गया है हालांकि दोनों को मार्क को संबोधित किया जाता है। क्या वह एक बग था? :-P –

1

सामान्य तौर पर, यह कार्यान्वयन पर निर्भर करता है। X86 (-64) लिनक्स पर, मेरा मानना ​​है कि मानक डौग ली मॉलोक एल्गोरिदम हमेशा एक मानक x86 पेज (4096 बाइट्स) आवंटित करेगा ताकि ऊपर वर्णित परिदृश्य के लिए, यह अतिरिक्त बाइट्स को समायोजित करने के लिए सीमाओं को रीसेट कर देगा। जब, आता है, तो 7bytes के बफर को PAGE_SIZE + 1 पर पुन: आवंटित करने का मानना ​​है कि मुझे लगता है कि यह उपलब्ध होने पर अगले संगत पृष्ठ को आवंटित करने का प्रयास करेगा।

वर्थ, निम्नलिखित पढ़ने यदि आप लिनक्स पर विकसित कर रहे हैं:

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

# echo 2 > /proc/sys/vm/overcommit_memory 

: मामले में लिनक्स परिस्थितियों में जहां यह होगा कम वांछनीय अचानक कुछ अनियमित रूप से चुने प्रक्रियाओं कम करने के लिए, और इसके अलावा कर्नल संस्करण पर्याप्त हाल है के तहत कार्यरत है, एक तरह एक आदेश का उपयोग कर इस overcommitting व्यवहार बंद कर सकता है कर्नेल प्रलेखन निर्देशिका, फ़ाइलें vm/overcommit-accounting और sysctl/vm.txt भी देखें।

0

FreeBSD और मैक ओएस एक्स reallocf है() फ़ंक्शन जो पास किए गए पॉइंटर को मुक्त करेगा जब अनुरोध की गई स्मृति आवंटित नहीं की जा सकती है (मैन रीलॉक देखें)।

+0

इसका उपयोग करने के बजाय, यदि आप वास्तव में उस व्यवहार को चाहते हैं तो ऐसा करने के लिए अपने स्वयं के फ़ंक्शन को लिखने के लिए यह बहुत अधिक समझदारी होगी। लेकिन मैं कल्पना नहीं कर सकता कि यह बहुत उपयोगी है - यह संभावित मूल्यवान डेटा फेंक रहा है। –

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