मालॉक और कॉलोक के बीच अंतर?


779

क्या करने में अंतर है:

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

या:

ptr = (char **) calloc (MAXELEMS, sizeof(char*));

जब मॉलॉक या इसके विपरीत कॉलोक का उपयोग करना एक अच्छा विचार है?



8
C में, आप उपरोक्त अधिक ptr = calloc(MAXELEMS, sizeof(*ptr));
उदारतापूर्वक

7
Calloc और malloc + memset vorpus.org/blog/why-does-calloc-exist
ddddavidee

2
@ddddavidee मैंने भी नेट पर इतने सारे उत्तरों से असंतुष्ट होने के बाद उस ब्लॉग को पाया। नाथनियल जे। स्मिथ अपने विश्लेषण के लिए 100+ SO अंक के हकदार हैं।
लाइफबैलेंस

जवाबों:


849

calloc()आपको शून्य-आरंभिक बफ़र malloc()देता है , जबकि स्मृति को असिंचित छोड़ देता है।

बड़े आवंटन के लिए, callocमुख्यधारा के OS के तहत अधिकांश कार्यान्वयन OS से ज्ञात-शून्य पृष्ठ (जैसे POSIX mmap(MAP_ANONYMOUS)या विंडोज के माध्यम से VirtualAlloc) प्राप्त करेंगे, इसलिए उन्हें उपयोगकर्ता-स्थान में लिखने की आवश्यकता नहीं है। यह सामान्य mallocहै और साथ ही ओएस से अधिक पृष्ठ कैसे मिलते हैं; callocबस ओएस की गारंटी का फायदा उठाता है।

इसका मतलब यह है कि callocमेमोरी अभी भी "साफ" और आलसी-आवंटित हो सकती है, और सिस्टम-आधारित साझा भौतिक पृष्ठ पर शून्य से कॉपी-ऑन-राइट मैप की जा सकती है। (वर्चुअल मेमोरी वाले सिस्टम को मान लें।)

कुछ कंपाइलर भी आपके लिए कॉलोक में मॉलॉक + मेमसेट (0) को ऑप्टिमाइज़ कर सकते हैं, लेकिन आपको स्पष्ट रूप से कॉलोक का उपयोग करना चाहिए यदि आप मेमोरी को पढ़ना चाहते हैं 0

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


यदि कोई OS नहीं है, तो एंबेडेड क्रियान्वयन callocइसे callocशून्य मेमोरी तक छोड़ सकता है , या यह एक फैंसी बहु-उपयोगकर्ता OS नहीं है जो प्रक्रियाओं के बीच सूचना लीक को रोकने के लिए पृष्ठों को शून्य करता है।

एम्बेडेड लिनक्स पर, मॉलोक mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), जो केवल कुछ एम्बेडेड कर्नेल के लिए सक्षम है, क्योंकि यह एक बहु-उपयोगकर्ता प्रणाली पर असुरक्षित है।


224
* आबंटित वेरिएंट बहुत मुनीम हैं - स्पष्ट-आबंटन, मेमोरी-आवंटन, पुनः आवंटन।
कास्काबेल

43
मॉलोक () का उपयोग करें यदि आप वह सब कुछ सेट करने जा रहे हैं जो आप आवंटित स्थान में उपयोग करते हैं। कॉलोक () का उपयोग करें यदि आप डेटा के कुछ हिस्सों को अनधिकृत रूप से छोड़ने जा रहे हैं - और यह शून्य भागों को शून्य करने के लिए फायदेमंद होगा।
जोनाथन लेफ़लर

268
callocजरूरी नहीं कि अधिक महंगा है, क्योंकि ओएस इसे गति देने के लिए कुछ चालें कर सकता है। मुझे पता है कि FreeBSD, जब इसे किसी भी निष्क्रिय सीपीयू समय मिलता है, तो इसका उपयोग एक सरल प्रक्रिया को चलाने के लिए होता है जो बस स्मृति के ब्लॉक किए गए ब्लॉकों को चारों ओर चला जाता है और ब्लॉक करता है और इस प्रकार एक ध्वज के साथ प्रक्रियाओं को चिह्नित करता है। इसलिए जब आप ऐसा करते हैं calloc, तो यह पहले ऐसे पूर्व-शून्य ब्लॉकों में से एक को खोजने की कोशिश करता है और बस आपको देता है - और सबसे अधिक संभावना है कि यह एक मिल जाएगा।
पावेल मिनाएव

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

18
@SteveJessop "सुरक्षित" सही शब्द नहीं है। मुझे लगता है कि "निर्धारक" बेहतर शब्द है। कोड जो विफलताओं के बजाय अधिक नियतात्मक है जो समय और डेटा अनुक्रमों पर निर्भर हैं, विफलताओं को अलग करना आसान होगा। कॉलोक कभी-कभी उस नियतत्ववाद, बनाम स्पष्ट आरंभीकरण को प्राप्त करने का एक आसान तरीका है।
डेनिस

362

एक कम ज्ञात अंतर यह है कि लिनक्स की तरह आशावादी मेमोरी आवंटन के साथ ऑपरेटिंग सिस्टम में, पॉइंटर द्वारा लौटाया mallocगया वास्तविक मेमोरी द्वारा समर्थित नहीं है जब तक कि प्रोग्राम वास्तव में इसे छूता नहीं है।

callocवास्तव में मेमोरी को छूता है (यह उस पर जीरो लिखता है) और इस तरह आपको यकीन होगा कि ओएस वास्तविक रैम (या स्वैप) के साथ आवंटन का समर्थन कर रहा है। यह भी यही कारण है कि यह मॉलोक की तुलना में धीमा है (न केवल इसे शून्य करना है, ओएस को संभवतः अन्य प्रक्रियाओं को स्वैप करके एक उपयुक्त मेमोरी क्षेत्र भी खोजना होगा)

उदाहरण के लिए देखें मलोक के व्यवहार के बारे में अधिक चर्चा के लिए यह एसओ प्रश्न


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

3
@ आर .. दिलचस्प नोट। लेकिन व्यवहार में, क्या ऐसे कार्यान्वयन जंगली में मौजूद हैं?
इसक सावो

10
सभी प्रकार के dlmallocकार्यान्वयन को छोड़ दें memsetयदि चंक को mmapनए अनाम पृष्ठों (या समतुल्य) के माध्यम से प्राप्त किया गया था । आमतौर पर इस तरह के आवंटन का उपयोग बड़े पैमाने पर विखंडन के लिए किया जाता है, 256k या तो शुरू होता है। मैं किसी भी कार्यान्वयन के बारे में नहीं जानता जो शून्य के खिलाफ तुलना लिखने से पहले शून्य को अपने से अलग करता है।
आर .. गिटहब स्टॉप हेल्पिंग ICE

1
omallocभी छोड़ देता है memset; callocकिसी भी ऐसे पृष्ठ को छूने की आवश्यकता नहीं है जो पहले से ही एप्लिकेशन (पेज कैश) द्वारा उपयोग नहीं किया जाता है। हालांकि, अत्यंत आदिम callocकार्यान्वयन अलग हैं।
मिराबिलोस

10
अगर यह ओएस से ताज़ा मेमोरी प्राप्त कर रहा है, तो ग्लिबक के कॉलॉक की जाँच करता है। यदि ऐसा है, तो यह जानता है कि इसे लिखने की आवश्यकता नहीं है, क्योंकि mmap (..., MAP_ANONYMOUS) ऐसी मेमोरी देता है जो पहले से ही शून्य है।
पीटर कॉर्ड्स

111

एक अक्सर-अनदेखी लाभ callocयह है कि (अनुरूप कार्यान्वयन) यह पूर्णांक अतिप्रवाह कमजोरियों के खिलाफ आपकी रक्षा करने में मदद करेगा। की तुलना करें:

size_t count = get_int32(file);
struct foo *bar = malloc(count * sizeof *bar);

बनाम

size_t count = get_int32(file);
struct foo *bar = calloc(count, sizeof *bar);

पूर्व एक छोटे से आवंटन और बाद में बफर overflows में परिणाम सकता है, अगर countसे अधिक है SIZE_MAX/sizeof *bar। उत्तरार्द्ध इस मामले में स्वचालित रूप से विफल हो जाएगा क्योंकि एक वस्तु जो बड़ी नहीं बनाई जा सकती है।

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


17
जाहिर तौर पर अंकगणितीय अतिप्रवाह 2002 में ओपनएसएसएच छेद का कारण बना। स्मृति-संबंधी कार्यों के साथ इस के खतरों पर ओपनबीएसडी का अच्छा लेख: undeadly.org/cgi?action=article&sid=2006040071917
फिलिप पी।

4
@KomradeP .: दिलचस्प। अफसोस की बात है कि आपके द्वारा जोड़ा गया लेख शुरुआत में गलत जानकारी देता है। साथ उदाहरण charहै नहीं एक अतिप्रवाह बल्कि एक कार्यान्वयन-परिभाषित रूपांतरण जब एक में परिणाम वापस बताए charवस्तु।
आर .. गिटहब स्टॉप हेल्पिंग ICE

यह केवल दृष्टांत प्रयोजन के लिए है। क्योंकि कंपाइलर को वैसे भी दूर करने की संभावना है। खदान इस राख में संकलित करती है: धक्का 1.
फिलिप पी।

1
@tristopia: मुद्दा यह नहीं है कि कोड सभी कार्यान्वयन पर शोषक है, लेकिन यह अतिरिक्त धारणाओं के बिना गलत है और इस प्रकार सही / पोर्टेबल उपयोग नहीं है।
आर .. गिटहब स्टॉप हेल्पिंग आईसीई

3
@tristopia: अगर आपकी सोच का तरीका " size_t64-बिट है तो कोई समस्या नहीं है", यह सोच का एक त्रुटिपूर्ण तरीका है जो सुरक्षा बगों को जन्म देने वाला है। size_tएक अमूर्त प्रकार है जो आकारों का प्रतिनिधित्व करता है, और 32-बिट संख्या और एक size_t( एक नोट के मनमाने ढंग से उत्पाद के बारे में सोचने का कोई कारण नहीं है : sizeof *barसिद्धांत रूप में 64-बिट सी कार्यान्वयन पर 2 ^ 32 से अधिक हो सकता है!) में फिट बैठता है size_t
आर .. गिटहब स्टॉप हेल्पिंग ICE

37

प्रलेखन कॉलॉक को मॉलोक की तरह दिखता है, जो स्मृति को शून्य-प्रारंभिक करता है; यह प्राथमिक अंतर नहीं है! कॉलोक का विचार स्मृति आवंटन के लिए कॉपी-ऑन-राइट शब्दार्थ को निरस्त करना है। जब आप कॉलॉक के साथ मेमोरी आवंटित करते हैं तो यह सभी मैप्स को उसी भौतिक पृष्ठ पर भेज देता है जिसे शून्य पर आरम्भ किया जाता है। जब आवंटित मेमोरी के किसी भी पृष्ठ को भौतिक पृष्ठ में लिखा जाता है तो उसे आवंटित किया जाता है। यह अक्सर हैश हैश टेबल बनाने के लिए उपयोग किया जाता है, उदाहरण के लिए चूंकि हैश के हिस्से जो खाली हैं वे किसी भी अतिरिक्त मेमोरी (पेज) द्वारा समर्थित नहीं हैं; वे खुशी से एकल शून्य-प्रारंभिक पृष्ठ पर इंगित करते हैं, जिसे प्रक्रियाओं के बीच भी साझा किया जा सकता है।

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

यहाँ विषय के बारे में एक अनुकूलन कहानी है: http://blogs.fau.de/hager/2007/05/08/benchmarking-fun-with-calloc-and-zero-pages/


26

आबंटित मेमोरी ब्लॉक के आकार में कोई अंतर नहीं है। callocसिर्फ भौतिक ऑल-जीरो-बिट्स पैटर्न के साथ मेमोरी ब्लॉक भरता है। व्यवहार में अक्सर यह माना जाता है कि आवंटित मेमोरी ब्लॉक में स्थित ऑब्जेक्ट्स में callocइनिटिलियल वैल्यू होती है जैसे कि उन्हें शाब्दिक रूप से इनिशियलाइज़ किया गया था 0, यानी पूर्णांकों का मान 0, फ्लोटिंग-पॉइंट वैरिएबल - वैल्यू ऑफ़ 0.0, पॉइंटर्स - उपयुक्त अशक्त-पॉइंटर वैल्यू होना चाहिए , और इसी तरह।

पांडित्य के दृष्टिकोण से, हालांकि calloc(और साथ ही memset(..., 0, ...)) केवल प्रकार की वस्तुओं को ठीक से ज़ीरो (प्रारंभिक) के साथ निर्धारित करने की गारंटी है unsigned char। बाकी सब कुछ ठीक से प्रारंभिक होने की गारंटी नहीं है और इसमें तथाकथित ट्रैप प्रतिनिधित्व शामिल हो सकता है , जो अपरिभाषित व्यवहार का कारण बनता है। दूसरे शब्दों में, unsigned charउपरोक्त सभी-शून्य-बिट्स पैटरम के अलावा किसी भी प्रकार के लिए एक अवैध मूल्य, ट्रैप प्रतिनिधित्व का प्रतिनिधित्व कर सकता है।

बाद में, तकनीकी कोरिगेंडा में C99 मानक में से एक में, सभी पूर्णांक प्रकारों के लिए व्यवहार को परिभाषित किया गया था (जो समझ में आता है)। यानी औपचारिक रूप से, वर्तमान C भाषा में आप केवल calloc(और memset(..., 0, ...)) के साथ पूर्णांक प्रकारों को प्रारंभ कर सकते हैं । सामान्य मामले में किसी और चीज को इनिशियलाइज़ करने के लिए इसका इस्तेमाल करने से सी भाषा के दृष्टिकोण से अपरिभाषित व्यवहार होता है।

व्यवहार में, callocकाम करता है, जैसा कि हम सभी जानते हैं :), लेकिन क्या आप इसका उपयोग करना चाहते हैं (ऊपर विचार करके) आप पर निर्भर है। मैं व्यक्तिगत रूप से इसे पूरी तरह से बचना पसंद करता हूं, mallocइसके बजाय उपयोग करें और अपनी खुद की इनिशियलाइज़ेशन करें।

अंत में, एक अन्य महत्वपूर्ण विवरण यह है कि तत्वों की संख्या से तत्व आकार को गुणा करके, callocअंतिम ब्लॉक आकार की आंतरिक रूप से गणना करना आवश्यक है । ऐसा करते समय, callocसंभव अंकगणित अतिप्रवाह के लिए देखना चाहिए। यदि असफल ब्लॉक आकार की सही गणना नहीं की जा सकती है तो यह असफल आवंटन (अशक्त सूचक) के परिणामस्वरूप होगा। इस बीच, आपका mallocसंस्करण अतिप्रवाह के लिए देखने का कोई प्रयास नहीं करता है। यह अतिप्रवाह होने पर कुछ "अप्रत्याशित" मात्रा में मेमोरी आवंटित करेगा।


"एक और महत्वपूर्ण विवरण" पैराग्राफ के अनुसार: ऐसा लगता है कि memset(p, v, n * sizeof type);एक समस्या है क्योंकि n * sizeof typeअतिप्रवाह हो सकता है। मुझे लगता है कि मैं for(i=0;i<n;i++) p[i]=v;मजबूत कोड के लिए एक पाश का उपयोग करने की आवश्यकता होगी ।
chux -

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

@chux नहीं, अगर nतत्वों के साथ एक सरणी मौजूद है जहां एक तत्व का आकार है sizeof type, तो n*sizeof typeअतिप्रवाह नहीं हो सकता है, क्योंकि किसी भी वस्तु का अधिकतम आकार इससे कम होना चाहिए SIZE_MAX
12431234123412341234123

@ 12431234123412341234123 एक सरणी आकार के बारे में सही है = SIZE_MAX, फिर भी यहाँ कोई सरणियाँ नहीं हैं। पॉइंटर से लौटाया calloc()गया आवंटित मेमोरी की तुलना में अधिक हो सकता है SIZE_MAX। कई प्रयोगों के लिए 2 आर्ग के उत्पाद सीमित करते हैं calloc()करने के लिए SIZE_MAX, अभी तक सी कल्पना है कि सीमा लागू नहीं है।
chux -

21

जॉर्ज हेगर के ब्लॉग पर कॉलोक () और शून्य पृष्ठों के साथ एक आलेख बेंचमार्किंग मज़ा

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


लिंक कहाँ है
रूपेश यादव

2
उत्तर की पहली पंक्ति में जॉर्ज हैगर के ब्लॉग का लिंक है।
आशीष चव्हाण

11

callocआम तौर malloc+memsetपर 0 है

आमतौर पर malloc+memsetस्पष्ट रूप से उपयोग करना थोड़ा बेहतर होता है , खासकर जब आप कुछ ऐसा कर रहे हों:

ptr=malloc(sizeof(Item));
memset(ptr, 0, sizeof(Item));

यह बेहतर है क्योंकि sizeof(Item)संकलन समय पर संकलक को पता है और संकलक ज्यादातर मामलों में इसे शून्य मेमोरी के लिए सर्वोत्तम संभव निर्देशों के साथ बदल देगा। दूसरी ओर यदि memsetहो रहा है calloc, तो आवंटन का पैरामीटर आकार callocकोड में संकलित नहीं किया memsetजाता है और वास्तविक को अक्सर कहा जाता है, जिसमें आमतौर पर बाइट-बाइट करने के लिए कोड होता है, जो लंबे समय तक सीमा तक भरते हैं, चक्र से भरने के लिए। sizeof(long)चंक्स में अप मेमोरी और अंत में बाइट-बाइट शेष स्थान को भरते हैं। यहां तक ​​कि अगर आबंटक कुछ कॉल करने के लिए पर्याप्त स्मार्ट है, aligned_memsetतब भी यह एक सामान्य लूप होगा।

एक उल्लेखनीय अपवाद तब होगा जब आप मेमोरी के बहुत बड़े हिस्से (कुछ पॉवर_ऑफ_ट्वो किलोबाइट्स) का मॉलोक / कॉलोक कर रहे हों, जिसमें केस आवंटन सीधे कर्नेल से किया जा सकता है। जैसा कि ओएस कर्नेल आमतौर पर सुरक्षा कारणों से दूर की जाने वाली सभी मेमोरी को शून्य कर देते हैं, स्मार्ट पर्याप्त कॉलोक बस इसे अतिरिक्त शून्य के साथ वापस कर सकता है। फिर से - यदि आप कुछ ऐसा कर रहे हैं जिसे आप जानते हैं कि वह छोटा है, तो आप मॉलोक + मेस्सेट प्रदर्शन-वार के साथ बेहतर हो सकते हैं।


+1 अनुस्मारक के लिए कि सिस्टम लाइब्रेरी में कार्यक्षमता का एक सामान्य कार्यान्वयन आवश्यक रूप से उपयोगकर्ता कोड में समान ऑपरेशन से तेज नहीं है।
पैट्रिक श्ल्टर

1
एक दूसरा बिंदु भी है जो इससे calloc()धीमा है malloc(): आकार के लिए गुणा। calloc()जेनेरिक गुणन (यदि size_t64 बिट्स बहुत महंगा 64 बिट्स * 64 बिट्स = 64 बिट्स ऑपरेशन है) का उपयोग करना आवश्यक है, जबकि मॉलॉक () में अक्सर एक संकलन समय स्थिर होगा।
पैट्रिक श्ल्टर

4
glibc calloc में यह तय करने के लिए कुछ स्मार्ट हैं कि कैसे लौटे हुए चंक को सबसे कुशलता से साफ किया जाए, जैसे कि कभी-कभी इसके केवल एक हिस्से को समाशोधन की आवश्यकता होती है, और 9 * sizeof (size_t) तक एक अनियंत्रित क्लियर भी। मेमोरी मेमोरी है, इसे एक बार में 3 बाइट्स साफ़ करना केवल इसलिए तेज नहीं होने वाला है क्योंकि आप इसे होल्ड करने के लिए उपयोग करने जा रहे हैं struct foo { char a,b,c; };callocहमेशा malloc+ से बेहतर है memset, यदि आप हमेशा पूरे mallocएड क्षेत्र को खाली करने जा रहे हैं । callocआकार * तत्वों में int अतिप्रवाह के लिए एक सावधान लेकिन कुशल जाँच है, भी।
पीटर कॉर्ड्स

8

अंतर 1:

malloc() आमतौर पर मेमोरी ब्लॉक को आवंटित किया जाता है और यह आरंभिक मेमोरी सेगमेंट है।

calloc() मेमोरी ब्लॉक को आवंटित करता है और सभी मेमोरी ब्लॉक को 0 में इनिशियलाइज़ करता है।

अंतर 2:

यदि आप malloc()वाक्यविन्यास पर विचार करते हैं, तो यह केवल 1 तर्क लेगा। नीचे दिए गए उदाहरण पर विचार करें:

data_type ptr = (cast_type *)malloc( sizeof(data_type)*no_of_blocks );

Ex: यदि आप int प्रकार के लिए मेमोरी के 10 ब्लॉक आवंटित करना चाहते हैं,

int *ptr = (int *) malloc(sizeof(int) * 10 );

यदि आप calloc()वाक्यविन्यास पर विचार करते हैं, तो यह 2 तर्क लेगा। नीचे दिए गए उदाहरण पर विचार करें:

data_type ptr = (cast_type *)calloc(no_of_blocks, (sizeof(data_type)));

Ex: यदि आप int प्रकार के लिए मेमोरी के 10 ब्लॉक आवंटित करना चाहते हैं और ZERO को सभी को प्रारंभ करें,

int *ptr = (int *) calloc(10, (sizeof(int)));

समानता:

दोनों malloc()और calloc()डिफ़ॉल्ट रूप से शून्य * वापस आ जाएगी अगर वे casted प्रकार नहीं कर रहे हैं।!


और आप data_type और cast_type को अलग क्यों रखते हैं?
बाहर बेचा

7

दो अंतर हैं।
सबसे पहले, तर्कों की संख्या में है। malloc()एकल तर्क (बाइट्स में आवश्यक मेमोरी) लेता है, जबकि calloc()दो तर्कों की आवश्यकता होती है।
दूसरे, आवंटित मेमोरी को malloc()इनिशियलाइज़ नहीं करता है, जबकि calloc()आवंटित मेमोरी को ज़ीरो को इनिशियलाइज़ करता है।

  • calloc()एक स्मृति क्षेत्र आवंटित करता है, लंबाई इसके मापदंडों का उत्पाद होगी। callocZERO के साथ मेमोरी को भरता है और पहले बाइट को पॉइंटर देता है। यदि यह पर्याप्त स्थान खोजने में विफल रहता है तो यह एक NULLपॉइंटर लौटाता है ।

सिंटेक्स: ptr_var=(cast_type *)calloc(no_of_blocks , size_of_each_block); यानीptr_var=(type *)calloc(n,s);

  • malloc()आवश्यक आकार की स्मृति का एक ब्लॉक आवंटित करता है और पहले बाइट के लिए एक संकेतक लौटाता है। यदि यह मेमोरी की आवश्यक राशि का पता लगाने में विफल रहता है तो यह अशक्त सूचक देता है।

सिंटेक्स: समारोह, एक तर्क है, जो बाइट की संख्या आवंटित करने के लिए ले, जबकि समारोह तत्वों की संख्या जा रहा है एक दो तर्क लेता है, और अन्य बाइट की संख्या उन तत्वों में से प्रत्येक के लिए आवंटित करने के लिए किया जा रहा है। इसके अलावा, आवंटित स्थान को शून्य से आरंभ करता है , जबकि ऐसा नहीं करता है।ptr_var=(cast_type *)malloc(Size_in_bytes);malloc()calloc()calloc()malloc()


6

calloc()समारोह है कि में घोषित किया जाता है <stdlib.h>हैडर का लाभ होता की एक जोड़ी प्रदान करता है malloc()कार्य करते हैं।

  1. यह किसी दिए गए आकार के कई तत्वों के रूप में मेमोरी आवंटित करता है, और
  2. यह उस मेमोरी को इनिशियलाइज़ करता है जिसे आवंटित किया गया है ताकि सभी बिट्स शून्य हों।

6

malloc()और calloc()सी मानक पुस्तकालय से कार्य हैं जो गतिशील मेमोरी आवंटन की अनुमति देते हैं, जिसका अर्थ है कि वे दोनों रनटाइम के दौरान मेमोरी आवंटन की अनुमति देते हैं।

उनके प्रोटोटाइप इस प्रकार हैं:

void *malloc( size_t n);
void *calloc( size_t n, size_t t)

दोनों के बीच मुख्य रूप से दो अंतर हैं:

  • व्यवहार: malloc()एक मेमोरी ब्लॉक को आवंटित करता है, इसे शुरू किए बिना, और इस ब्लॉक से सामग्री को पढ़ने से कचरा मान उत्पन्न होगा। calloc()दूसरी ओर, एक मेमोरी ब्लॉक आवंटित करता है और इसे शून्य पर आरंभीकृत करता है, और जाहिर है कि इस ब्लॉक की सामग्री को पढ़ने से शून्य हो जाएगा।

  • सिंटैक्स: malloc()1 तर्क लेता है (आकार आवंटित किया जाना है), और calloc()दो तर्क लेता है (आवंटित किए जाने वाले ब्लॉक की संख्या और प्रत्येक ब्लॉक का आकार)।

दोनों से वापसी का मान यदि सफल हो तो मेमोरी के आवंटित ब्लॉक के लिए एक संकेतक है। अन्यथा, NULL को स्मृति आबंटन विफलता का संकेत देते हुए लौटा दिया जाएगा।

उदाहरण:

int *arr;

// allocate memory for 10 integers with garbage values
arr = (int *)malloc(10 * sizeof(int)); 

// allocate memory for 10 integers and sets all of them to 0
arr = (int *)calloc(10, sizeof(int));

उसी कार्यक्षमता calloc()का उपयोग करके प्राप्त किया जा सकता है malloc()और memset():

// allocate memory for 10 integers with garbage values   
arr= (int *)malloc(10 * sizeof(int));
// set all of them to 0
memset(arr, 0, 10 * sizeof(int)); 

ध्यान दें कि यह तेजी malloc()से होने के calloc()बाद से अधिमानतः उपयोग किया जाता है । यदि मानों को शून्य-प्रारंभिक करना है, तो calloc()इसके बजाय उपयोग करें ।


5

एक अंतर जो अभी तक उल्लेख नहीं किया गया है: आकार सीमा

void *malloc(size_t size)तक ही आवंटित किया जा सकता है SIZE_MAX

void *calloc(size_t nmemb, size_t size);के बारे में आवंटित कर सकते हैं SIZE_MAX*SIZE_MAX

इस क्षमता का उपयोग अक्सर रैखिक पतों के साथ कई प्लेटफार्मों में नहीं किया जाता है। इस तरह की प्रणालियों के calloc()साथ सीमा होती है nmemb * size <= SIZE_MAX

एक प्रकार के 512 बाइट्स पर विचार करें जिसे disk_sectorकोड कहा जाता है और कोड बहुत सारे सेक्टर का उपयोग करना चाहता है । यहां, कोड केवल SIZE_MAX/sizeof disk_sectorक्षेत्रों तक का उपयोग कर सकते हैं ।

size_t count = SIZE_MAX/sizeof disk_sector;
disk_sector *p = malloc(count * sizeof *p);

निम्नलिखित पर विचार करें जो एक और भी बड़े आवंटन की अनुमति देता है।

size_t count = something_in_the_range(SIZE_MAX/sizeof disk_sector + 1, SIZE_MAX)
disk_sector *p = calloc(count, sizeof *p);

अब अगर इस तरह की व्यवस्था इतने बड़े आवंटन की आपूर्ति कर सकती है तो यह एक और मामला है। अधिकांश आज नहीं करेंगे। फिर भी यह कई वर्षों के लिए हुआ है जब SIZE_MAX65535 था। मूर के कानून को देखते हुए , यह संदेह है कि यह 2030 में कुछ मेमोरी मॉडल के साथ SIZE_MAX == 4294967295और 100 जीबीटी में मेमोरी पूल के साथ होगा ।


2
आम तौर पर, size_t एक कार्यक्रम को संभाल सकने वाली सबसे बड़ी वस्तु के आकार को धारण करने में सक्षम होगा। ऐसी प्रणाली जहां size_t 32 बिट्स है, 4294967295 बाइट्स से बड़े आवंटन को संभालने में सक्षम होने की संभावना नहीं है, और एक सिस्टम जो आवंटन को संभालने में सक्षम होगा, वह आकार लगभग निश्चित रूप size_tसे 32 बिट्स से बड़ा बना देगा । एकमात्र सवाल यह है कि क्या callocउन मूल्यों का उपयोग किया SIZE_MAXजा सकता है जिनके उत्पाद से अधिक होने पर एक छोटे से आवंटन के लिए सूचक को वापस करने के बजाय शून्य उपज पर भरोसा किया जा सकता है।
सुपरकैट

अपने सामान्यीकरण के बारे में सहमत हों , फिर भी सी कल्पना calloc()आवंटन से अधिक की अनुमति देता है SIZE_MAX। यह 16-बिट के साथ अतीत में हुआ है size_tऔर जैसे - जैसे स्मृति सस्ता होती जा रही है, मुझे लगता है कि कोई कारण नहीं कि यह सामान्य होने पर भी आगे नहीं बढ़ेगा ।
chux -

1
सी मानक एक आवंटन का अनुरोध करने के लिए कोड के लिए संभव बनाता है जिसका आकार अधिक होता है SIZE_MAX। यह निश्चित रूप से आवश्यक नहीं है कि ऐसी कोई परिस्थिति हो जिसके तहत ऐसा आवंटन सफल हो सके; मुझे यकीन नहीं है कि यह सुनिश्चित करने से कोई विशेष लाभ है कि कार्यान्वयन जो इस तरह के आवंटन को संभाल नहीं सकते हैं, उन्हें वापस लौटना चाहिए NULL(विशेषकर यह कि यह कुछ कार्यान्वयन के लिए सामान्य है कि mallocरिटर्न पॉइंटर्स स्पेस में हैं जो अभी तक प्रतिबद्ध नहीं है और उपलब्ध नहीं हो सकता है जब कोड वास्तव में उपयोग करने की कोशिश करता है। यह)।
सुपरकैट

इसके अलावा, जहाँ अतीत में ऐसी प्रणालियाँ रही होंगी जिनकी उपलब्ध पता सीमा सबसे बड़े प्रतिनिधित्व योग्य पूर्णांक को पार कर गई थी, फिर भी मुझे कभी भी होने की कोई वास्तविक संभावना नहीं दिखती है, क्योंकि इसके लिए अरबों गीगाबाइट की भंडारण क्षमता की आवश्यकता होगी। यहां तक ​​कि अगर मूर का कानून जारी रहा, उस बिंदु से जा रहा है जहां 32 बिट्स उस बिंदु के लिए पर्याप्त होना बंद हो जाते हैं जहां 64 बिट्स पर्याप्त हो जाते हैं, उस बिंदु से दो बार लगेंगे जहां 16 बिट्स उस बिंदु पर पर्याप्त थे जहां 32 था 'टी।
सुपरकैट

1
एक कार्यान्वयन जो 4 जी से अधिक के एकल आवंटन को समायोजित कर सकता है, उसे परिभाषित क्यों नहीं size_tकरेगा uint64_t?
सुपरकैट

2

ब्लॉक की संख्या: मॉलॉक ()
अनुरोधित मेमोरी के सिंगल ब्लॉक को असाइन करता है,
कॉलॉक () अनुरोधित मेमोरी के कई ब्लॉकों को असाइन करता है

प्रारंभ:
मॉलोक () - स्पष्ट नहीं है और आवंटित स्मृति को इनिशियलाइज़ करता है।
calloc () - आवंटित स्मृति को शून्य से आरंभ करता है।

गति:
मॉलोक () तेज है।
कॉलॉक () मॉलॉक () की तुलना में धीमा है।

तर्क और वाक्य रचना:
मॉलॉक () 1 तर्क लेता है:

  1. बाइट्स

    • आवंटित किए जाने वाले बाइट्स की संख्या

कॉलोक () 2 तर्क लेता है:

  1. लंबाई

    • स्मृति के ब्लॉक की संख्या आवंटित की जानी है
  2. बाइट्स
    • मेमोरी के प्रत्येक ब्लॉक पर बाइट्स की संख्या आवंटित की जानी है
void *malloc(size_t bytes);         
void *calloc(size_t length, size_t bytes);      

स्मृति आबंटन
की क्षमता : मैलोक फ़ंक्शन उपलब्ध ढेर से वांछित 'आकार' की स्मृति प्रदान करता है।
कॉलोक फ़ंक्शन मेमोरी को असाइन करता है जो कि 'संख्या * आकार' के बराबर है।

नाम पर अर्थ:
नाम मॉलोक का अर्थ है "मेमोरी आवंटन"।
कॉलॉक नाम का अर्थ है "सन्निहित आवंटन"।

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