2011-02-07 17 views

उत्तर

1

मैं इसे अधिकतर कार्यान्वयन विशिष्ट कहूंगा। कुछ कार्यान्वयन विफल होने की संभावना हो सकती है। प्रोग्राम के अन्य हिस्सों में रीयलोक इच्छा से पहले असफल हो सकता है। हमेशा रक्षात्मक रहें और जांचें कि यह असफल रहा है या नहीं।

और पुराना पॉइंटर को फिर से शुरू करने का प्रयास करने के लिए याद रखें।

ptr=realloc(ptr,10); 

हमेशा एक संभावित स्मृति रिसाव है।

हमेशा यह नहीं बल्कि इस तरह कार्य करें:

void *tmp=ptr; 
if(ptr=realloc(ptr,10)==NULL){ 
    free(tmp); 
    //handle error... 
} 
+0

मेरा मानना ​​है कि केवल एक चीज मानक इसके बारे में कहा गया है कि एक अशक्त सूचक दिया जाता है कारणों के बारे में "[मैं] च अंतरिक्ष आवंटित नहीं किया जा सकता है", कुछ भी नहीं और अधिक विशिष्ट है। – Mormegil

+0

जब आप नए डेटा के लिए जगह नहीं बना सकते हैं तो पुराना डेटा फेंकना शायद अधिकांश अनुप्रयोगों के लिए सही व्यवहार नहीं है ... –

+0

@R .. अच्छा, यह सच है। मैं केवल सामान्य स्मृति रिसाव की चेतावनी दे रहा था – Earlz

0

आप दो प्रश्न हैं।

संभावना है कि malloc या realloc असफल अधिकांश आधुनिक प्रणाली पर नगण्य हैं। यह तब होता है जब आप वर्चुअल मेमोरी से बाहर हो जाते हैं। आपका सिस्टम स्मृति तक पहुंचने में विफल रहेगा और इसे आरक्षित करने पर नहीं।

W.r.t विफलता realloc और malloc लगभग बराबर हैं। एकमात्र कारण यह है कि realloc अतिरिक्त विफल हो सकता है कि आप इसे एक खराब तर्क देते हैं, वह स्मृति है जिसे malloc या realloc के साथ आवंटित नहीं किया गया था या जो पहले free डी था।

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

+0

* * * * आवंटन * * पर पहुंचने में विफलता एक "आधुनिक" व्यवहार नहीं है। यह एक आलसी व्यवहार है। कमिट एकाउंटिंग कठिन है, और लिनक्स के विकास में शुरुआती, हर कोई सही होने के लिए बहुत आलसी था। मजबूत यूनिक्स सिस्टम ने दशकों से उचित प्रतिबद्धता की है, और इन दिनों लिनक्स को उचित लेखांकन के लिए भी कॉन्फ़िगर किया जा सकता है। –

+0

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

+0

@R .: आवंटन के बाद, आप अस्थायी रूप से' SIGSEGV' और 'SIGBUS' और पृष्ठों तक पहुंचने के लिए उन्हें लूप करें। इसके द्वारा आप कम से कम त्रुटि को सीमित कर सकते हैं, और फिर कृपापूर्वक विफल हो सकते हैं। आवंटन के लिए शुरुआती ओवरहेड ध्यान देने योग्य होगा, लेकिन अगर आवंटित सभी मेमोरी वास्तव में उपयोग की जाती है तो अमूर्त लागत सहनशील होगी, मुझे लगता है। –

10

आवंटन कार्यों में से कोई (malloc, realloc, calloc, और POSIX पर, posix_memalign) निम्न कारणों से किसी के लिए विफल हो सकता है, और संभवतः दूसरों:

  • आप अपने पूरे आभासी पता उपयोग कर चुके हों अंतरिक्ष, या कम से कम इसका उपयोग करने योग्य हिस्सा। 32-बिट मशीन पर, केवल 4 जीबी के पते हैं, और संभवतः 1 जीबी या तो ओएस कर्नेल द्वारा उपयोग के लिए आरक्षित है। यहां तक ​​कि यदि आपकी मशीन में 16 जीबी की भौतिक मेमोरी है, तो एक ही प्रक्रिया इसके लिए पते के मुकाबले अधिक उपयोग नहीं कर सकती है।
  • आपने अपनी वर्चुअल एड्रेस स्पेस का उपयोग नहीं किया है, लेकिन आपने इसे इतनी बुरी तरह विभाजित कर दिया है कि अनुरोधित आकार के पते की कोई भी संगत श्रृंखला उपलब्ध नहीं है। यह हो सकता है (32-बिट मशीन पर) यदि आप सफलतापूर्वक 6 512 एमबी ब्लॉक आवंटित करते हैं, तो हर दूसरे को मुक्त करें, फिर 1 जीबी ब्लॉक आवंटित करने का प्रयास करें। बेशक छोटे स्मृति आकार के साथ कई अन्य उदाहरण हैं।
  • आपकी मशीन भौतिक मेमोरी से बाहर हो गई है, या तो आपके स्वयं के प्रोग्राम के कारण यह सब इस्तेमाल किया गया है, या मशीन पर चल रहे अन्य प्रोग्राम इसे सब कुछ इस्तेमाल कर रहे हैं। कुछ सिस्टम (डिफ़ॉल्ट कॉन्फ़िगरेशन में लिनक्स) ओवरकिट, जिसका अर्थ malloc इस स्थिति में विफल नहीं होगा, लेकिन इसके बाद ओएस बाद में एक या अधिक प्रोग्रामों को मार देगा जब यह पता चलता है कि वास्तव में पर्याप्त भौतिक स्मृति नहीं है।लेकिन मजबूत सिस्टम (ओवरकमिट अक्षम के साथ लिनक्स समेत) पर, malloc विफल हो जाएगा यदि कोई भौतिक स्मृति शेष नहीं है।

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

4

आप इस तरह से काम कर के रूप में realloc सोचना चाहिए:

void *realloc(void *oldptr, size_t newsize) 
{ 
    size_t oldsize = __extract_size_of_malloc_block(oldptr); 
    void *newptr = malloc(newsize); 

    if (!newptr) 
    return 0; 

    if (oldsize > newsize) 
    oldsize = newsize; 

    memcpy(newptr, oldptr, oldsize); 
    free(oldptr); 
    return newptr; 
} 

कार्यान्वयन कि अधिक कुशलता से विशिष्ट मामलों करने में सक्षम हो सकता है, लेकिन एक कार्यान्वयन है कि वास्तव में काम करता है दिखाया गया है 100% सही है। इसका मतलब है कि realloc(ptr, newsize) किसी भी समय विफल हो सकता है malloc(newsize) विफल हो गया होगा; विशेष रूप से यह विफल हो सकता है भले ही आप आवंटन को कम कर रहे हों।

अब, वहाँ malloc विफलताओं से उबरने की कोशिश नहीं है, लेकिन बजाय एक समारोह (आमतौर पर xmalloc कहा जाता है) में malloc लपेटकर के लिए एक मजबूत मामला है कि कार्यक्रम तुरंत अगर malloc विफल रहता है समाप्त हो जाता है है आधुनिक डेस्कटॉप सिस्टम पर; स्वाभाविक रूप से एक ही तर्क realloc पर लागू होता है। मामला है:

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

तर्क 1 और 2 एम्बेडेड या मोबाइल सिस्टम (अभी तक!) पर लागू नहीं होते हैं लेकिन तर्क 3 अभी भी मान्य है।

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

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