2013-02-22 30 views
8

मैं उलझन में हूं, malloc के साथ मेमोरी आवंटित करते समय आपको एक आकार प्रदान करना होगा, हालांकि, कभी-कभी ऐसा होता है कि आपको उस बिंदु पर जिस आकार की आवश्यकता है उसे नहीं पता है ताकि आप या तो एक विशाल आवंटित कर सकें स्मृति की मात्रा (जो बहुत बुद्धिमान नहीं है क्योंकि आप शायद इसका उपयोग नहीं कर रहे हैं) या आप realloc का उपयोग करते हैं जब प्रारंभिक बफर आकार बहुत छोटा हो जाता है। क्या ये दो विकल्प मान्य हैं? दूसरा अच्छा लगता है, हालांकि, दस्तावेज़ कहते हैं कि realloc...may move the memory block to a new location जो स्थिति को संभालने के लिए बहुत बुरे विचार/कड़ी मेहनत की तरह लगता है (उदाहरण के लिए यदि आपके पास realloc पर कॉल करने के पल में एक ही पते पर इंगित करने वाले एकाधिक पॉइंटर्स हैं तो वे सभी अमान्य हो जाते हैं) I ' मैं सी के साथ एक शुरुआत कर रहा हूं, क्या कोई मुझे बता सकता है कि उस परिस्थिति को कैसे संभालना है जिसमें आपके पास एक बफर है जो बहुत सारी स्मृति पर कब्जा करने के लिए बढ़ सकता है या नहीं।एक बफर के लिए आकार चुनना

+4

यदि आपके पास एक ही पते पर इंगित करने वाले एकाधिक पॉइंटर्स हैं, तो हाँ, आपने मूल पॉइंटर चर पर realloc() द्वारा लौटाए गए नए पॉइंटर को आवंटित करते समय सभी पॉइंटर्स अपडेट किए हैं। यह करना बहुत मुश्किल नहीं है। लेकिन तथ्य यह है कि आपको एक ही पते पर इशारा करते हुए बहुत से पॉइंटर्स अपडेट करना होगा, खराब डिजाइन की तरह लगता है। –

+2

'stdio.h' में 'BUFSIZ' मैक्रो का उपयोग करके और जब भी आप अंतरिक्ष से बाहर निकलते हैं तो इसे डुप्लिकेट करना आम दृष्टिकोण है। –

+0

इसके अलावा, कुछ प्लेटफॉर्म-निर्भर बदसूरत हैक्स में 'malloc_size()' et al का उपयोग करना शामिल है। –

उत्तर

5

यह कभी कभी होता है कि आप आकार आप उस बिंदु पर की जरूरत है पता नहीं है तो आप या तो alloc स्मृति की एक बड़ी राशि (जो नहीं लग बहुत बुद्धिमान है क्योंकि आप शायद इसका उपयोग नहीं करेंगे सभी) या जब आप प्रारंभिक बफर आकार बहुत छोटा हो जाता है तो आप रीयलोक का उपयोग करते हैं। क्या ये दो विकल्प मान्य हैं?

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

केवल जब आप वास्तव में कुछ लिखते हैं, तो ओएस इसके लिए स्मृति आरक्षित करेगा। तो कॉलोक का उपयोग न करें, क्योंकि यह स्मृति को आरंभ करता है, यानी इसमें कुछ लिखना।

तो यदि आपको नहीं पता कि आपको वास्तव में कितनी आवश्यकता होगी, तो बस पता लगाने वाले डेटा की विशेषताओं के द्वारा पता स्थान के एक बड़े हिस्से को मॉल करें, जिसके लिए आप आसानी से जो कुछ भी पकड़ लेंगे उम्मीद कर रहे हैं एक बार जब आप इसे स्मृति में प्राप्त कर लेंगे, तो आप आवंटन को कम करने के लिए realloc का उपयोग कर सकते हैं। रीयलोक कोई आवंटन घटाने पर डेटा को कभी भी स्थानांतरित नहीं करेगा, सभी लागू करने के लिए।

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

हालांकि आप स्मृति अतिसंवेदनशीलता को बंद कर सकते हैं; उच्च विश्वसनीयता प्रणाली पर दृढ़ता से अनुशंसित।

+0

बहुत ही रोचक जवाब, हालांकि, यदि आप डेटा अनुक्रमिक लिखते हैं, तो जैसे ही आप पहली टुकड़ा लिखते हैं, पूरा बफर आवंटित हो जाता है। तो आप बहुत ज्यादा लाभ नहीं उठाते हैं। केवल तभी जब आप एक बार में अपना डेटा लिखते हैं। किसी भी मामले में, 'कॉलोक'/'malloc' के संबंध में लिया गया बिंदु, धन्यवाद। – Meda

+2

@ मेडा, पूरे बफर नहीं। अगर मैं स्मृति के 1 एम को malloc, और पहले बाइट स्पर्श, प्रणाली स्मृति की एक पृष्ठ (पारंपरिक रूप से 4k लेकिन आधुनिक सिस्टम में बड़ा हो सकता है) पूरी श्रृंखला नहीं होगा। –

+0

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

3

आप सही हैं - वे आपके दो विकल्प बहुत अधिक हैं। आप थोड़ा सा सारण करके "एकाधिक पॉइंटर्स" समस्या के आसपास काम कर सकते हैं। यदि इसके बजाय सूचक malloc सीधे द्वारा दिया आसपास पास करने का, आप इसे एक और डेटा संरचना में रहना:

struct malloc_wrapper 
{ 
    void *p; 
} wrapper; 

wrapper.p = malloc(INITIAL_SIZE); 

कि डेटा संरचना के बजाय चारों ओर और संकेत गुजरती हैं, आप किसी भी समय p बदल सकते हैं और किसी को भी, जो शेयरों अपने नए संरचना करने के लिए सूचक तदनुसार अपडेट कर दिया जाएगा:

void *tmp = realloc(somepointertowrapper->p, NEW_SIZE); 

/* check tmp to ensure it's not NULL. That indicates a failure 
* to realloc and the original pointer passed into realloc 
* remains valid. 
*/ 

somepointertowrapper->p = tmp; 
+0

धन्यवाद, यह अच्छा लगता है। – Meda

+0

आवंटन विफलताओं का पता लगाने के लिए इसे सूचक को निर्दिष्ट करने से पहले हमेशा 'realloc' से परिणाम की जांच करें। ध्यान रखें कि 'realloc' एक ** हॉरबल ** इंटरफ़ेस है क्योंकि यह सभी लोगों के लिए सभी चीजों की कोशिश करता है। मैं मजाक नहीं कर रहा हूं: आप 'मॉलोक' और 'फ्री' और * रीयलोक 'के साथ * सब कुछ * का उपयोग करने से बच सकते हैं। –