सी गतिशील स्मृति आवंटन: Difference between revisions
(TEXT) |
(TEXT) |
||
Line 130: | Line 130: | ||
FreeBSD 7.0 और NetBSD 5.0 के बाद से, पुराने <code>malloc</code> कार्यान्वयन ([[Poul-Henning Kamp|पॉल-हेनिंग कैंप]] द्वारा phkmalloc) को जेसन इवांस द्वारा लिखित [http://jemalloc.net/ jemalloc] द्वारा प्रतिस्थापित किया गया था। इसका मुख्य कारण बहु सूत्रण के संबंध में phkmalloc की मापनीयता की कमी थी। लॉक विवाद से बचने के लिए, jemalloc प्रत्येक सीपीयू के लिए अलग "एरेनास" का उपयोग करता है। बहु सूत्रण अनुप्रयोग में प्रति सेकंड आवंटन की संख्या को मापने वाले प्रयोगों से पता चला है कि यह इसे थ्रेड्स की संख्या के साथ रैखिक रूप से पैमाना करता है, जबकि phkmalloc और डीएलमॉलोक दोनों के लिए प्रदर्शन थ्रेड्स की संख्या के व्युत्क्रमानुपाती था।<ref>{{cite web |url=http://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf |title=A Scalable Concurrent malloc(3) Implementation for FreeBSD |first=Jason |last=Evans |date=16 April 2006 |access-date=18 March 2012 }}</ref> | FreeBSD 7.0 और NetBSD 5.0 के बाद से, पुराने <code>malloc</code> कार्यान्वयन ([[Poul-Henning Kamp|पॉल-हेनिंग कैंप]] द्वारा phkmalloc) को जेसन इवांस द्वारा लिखित [http://jemalloc.net/ jemalloc] द्वारा प्रतिस्थापित किया गया था। इसका मुख्य कारण बहु सूत्रण के संबंध में phkmalloc की मापनीयता की कमी थी। लॉक विवाद से बचने के लिए, jemalloc प्रत्येक सीपीयू के लिए अलग "एरेनास" का उपयोग करता है। बहु सूत्रण अनुप्रयोग में प्रति सेकंड आवंटन की संख्या को मापने वाले प्रयोगों से पता चला है कि यह इसे थ्रेड्स की संख्या के साथ रैखिक रूप से पैमाना करता है, जबकि phkmalloc और डीएलमॉलोक दोनों के लिए प्रदर्शन थ्रेड्स की संख्या के व्युत्क्रमानुपाती था।<ref>{{cite web |url=http://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf |title=A Scalable Concurrent malloc(3) Implementation for FreeBSD |first=Jason |last=Evans |date=16 April 2006 |access-date=18 March 2012 }}</ref> | ||
=== [[ओपनबीएसडी]] का मॉलोक === | === [[ओपनबीएसडी]] का मॉलोक === | ||
<code>malloc</code> फलन के ओपनबीएसडी का कार्यान्वयन एमएमएपी का उपयोग करता है। एक पृष्ठ से बड़े आकार के अनुरोधों के लिए, संपूर्ण आवंटन <code>mmap</code> का उपयोग करके पुनर्प्राप्त किया जाता है; कई "बाल्टी पृष्ठों" के भीतर, <code>malloc</code> द्वारा अनुरक्षित स्मृति पूल से छोटे आकार निर्दिष्ट किए जाते हैं, जिन्हें एमएमएपी के साथ भी आवंटित किया जाता है।<ref>{{cite web|url=http://bxr.su/OpenBSD/lib/libc/stdlib/malloc.c |title=libc/stdlib/malloc.c |website=BSD Cross Reference, OpenBSD src/lib/}}</ref>{{better source needed|date=November 2015}} मुक्त करने के लिए एक कॉल पर, स्मृति को जारी किया जाता है और मुनमैप का उपयोग करके प्रक्रिया पता स्थान से <code>munmap</code> किया जाता है। इस प्रणाली को ओपनबीएसडी के हिस्से के रूप में कार्यान्वित [[एड्रेस स्पेस लेआउट रैंडमाइजेशन]] और गैप पेज सुविधाओं का लाभ उठाकर सुरक्षा में सुधार करने के लिए डिज़ाइन किया गया है। <code>mmap</code> [[सिस्टम कॉल|प्रणाली कॉल]], और उपयोग-बाद-मुक्त बग का पता लगाने के लिए- चूंकि एक बड़ी स्मृति आवंटन मुक्त होने के बाद पूरी तरह से मैप नहीं किया गया है, आगे के उपयोग से विभाजन की गलती और क्रमादेश की समाप्ति का कारण बनता है। | |||
=== होर्ड मॉलोक === | === होर्ड मॉलोक === | ||
{{main|Hoard memory allocator}} | {{main|Hoard memory allocator}} |
Revision as of 20:27, 5 March 2023
C standard library (libc) |
---|
General topics |
Miscellaneous headers |
सी गतिशील स्मृति आवंटन, सी क्रमादेशन भाषा में सी क्रमादेशन भाषा में प्रकार्य के समूह के माध्यम से मॉलोक, रियललोक, कॉलोक, एलायंस_आलोक और निःशुल्कके माध्यम से गतिशील स्मृति आवंटन के लिए मैनुअल स्मृति प्रबंधन करने को संदर्भित करता है।[1][2][3]
C++ क्रमादेशन भाषा में ये प्रकार्य सम्मिलित हैं; तथापि, ऑपरेटर नए और डिलीट प्रचालक समान कार्यक्षमता प्रदान करते हैं और उस भाषा के लेखकों द्वारा अनुशंसित होते हैं।[4] फिर भी, ऐसी कई स्थितियाँ हैं जिनमें नए/डिलीट का उपयोग करना अनुप्रयोज्य नहीं होता है, जैसे कचरा संग्रहण कोड या प्रदर्शन-संवेदनशील कोड, और उच्च-स्तरीय नए प्रचालक के बदले मॉलोक और नियोजन नए के संयोजन की आवश्यकता हो सकती है।
मॉलोक द्वारा उपयोग किए जाने वाले वास्तविक स्मृति आवंटन तंत्र के कई अलग-अलग कार्यान्वयन उपलब्ध हैं। निष्पादन समय और आवश्यक स्मृति दोनों में उनका प्रदर्शन भिन्न होता है।
तर्क
सी क्रमादेशन भाषा स्मृति को स्थिर, स्वचालित या गतिशील रूप से प्रबंधित करती है। स्थिर-अवधि चर मुख्य स्मृति में आवंटित किए जाते हैं, सामान्यतः क्रमादेश के निष्पादन योग्य कोड के साथ, और क्रमादेश के जीवनकाल के लिए बने रहते हैं; स्वचालित-अवधि चर स्टैक पर आवंटित किए जाते हैं और आते और जाते हैं जैसे प्रकार्य को कहा जाता है और वापस आते हैं। स्थैतिक-अवधि और स्वचालित-अवधि चर के लिए, आवंटन का आकार संकलन-समय स्थिर होना चाहिए (चर-लंबाई स्वचालित सरणी के मामले को छोड़कर)[5]। यदि आवश्यक आकार कार्यावधि तक ज्ञात नहीं है (उदाहरण के लिए, यदि मनमाना आकार का डेटा उपयोगकर्ता या डिस्क फ़ाइल से पढ़ा जा रहा है), तो निश्चित आकार के डेटा वस्तुओं का उपयोग करना अपर्याप्त है।
आवंटित स्मृति का जीवनकाल भी चिंता का कारण बन सकता है। सभी स्थितियों के लिए न तो स्थिर- और न ही स्वचालित-अवधि स्मृति पर्याप्त है। स्वचालित-आवंटित डेटा कई प्रकार्य कॉलों में नहीं बना रह सकता है, जबकि स्थैतिक डेटा क्रमादेश के जीवन के लिए बना रहता है चाहे इसकी आवश्यकता हो या नहीं। कई स्थितियों में क्रमादेशर को आबंटित स्मृति के जीवनकाल के प्रबंधन में अधिक सुनम्यता की आवश्यकता होती है।
गतिशील स्मृति आवंटन का उपयोग करके इन सीमाओं से बचा जाता है, जिसमें स्मृति अधिक स्पष्ट रूप से (लेकिन अधिक लचीला) प्रबंधित होती है, सामान्यतः इसे मुक्त संचित (अनौपचारिक रूप से "ढेर" कहा जाता है),[citation needed] से आवंटित करके, इस उद्देश्य के लिए संरचित स्मृति का एक क्षेत्र है। सी में, हीप पर स्मृति के ब्लॉक को आवंटित करने के लिए लाइब्रेरी फलन मैलोक
का उपयोग किया जाता है। क्रमादेश स्मृति के इस ब्लॉक को एक सूचक के माध्यम से अभिगम करता है जो मॉलोक रिटर्न करता है। जब स्मृति की आवश्यकता नहीं रह जाती है,तो सूचक को मुक्त करने के लिए पास किया जाता है जो स्मृति को आवंटन कर देता है ताकि इसे अन्य उद्देश्यों के लिए उपयोग किया जा सके।
सी के मूल विवरण ने संकेत दिया कि कॉलोक और सी मुक्त
मानक लाइब्रेरी में थे, लेकिनमॉलोक
नहीं थे। यूनिक्स के लिए भंडारण प्रबंधक के सरल मॉडल कार्यान्वयन के लिए कोड आवंटन के साथ दिया गया था और उपयोगकर्ता अंतरापृष्ठ कार्यों के रूप में मुक्त था, और संचालन प्रणाली से स्मृति का अनुरोध करने के लिए sbrk प्रणाली कॉल का उपयोग कर रहा था।[6] छठा संस्करण यूनिक्स प्रलेखन आवंटन और मुक्त को निम्न-स्तरीय स्मृति आवंटन कार्यों के रूप में देता है।[7] उनके आधुनिक रूप में मॉलोक और मुक्त दिनचर्या पूरी तरह से 7वें संस्करण यूनिक्स हस्तचालित में वर्णित हैं।[8][9]
कुछ प्लेटफॉर्म लाइब्रेरी या आंतरिक फलन कॉल प्रदान करते हैं जो हीप (जैसेalloca())
[10]के बदले सी स्टैक से कार्यावधि गतिशील आवंटन की अनुमति देते हैं। कॉलिंग कार्य समाप्त होने पर यह स्मृति स्वचालित रूप से मुक्त हो जाती है।
कार्यों का अवलोकन
सी गतिशील स्मृति आवंटन कार्यों को stdlib.h
हेडर (cstdlib
सी ++ में हेडर) में परिभाषित किया गया है।[1]
कार्य | विवरण |
---|---|
malloc
|
बाइट्स की निर्दिष्ट संख्या आवंटित करता है |
aligned_alloc
|
निर्दिष्ट संरेखण पर बाइट्स की निर्दिष्ट संख्या आवंटित करता है |
realloc
|
स्मृति के निर्दिष्ट ब्लॉक के आकार को बढ़ाता या घटाता है, यदि आवश्यक हो तो इसे स्थानांतरित करता है |
calloc
|
बाइट्स की निर्दिष्ट संख्या आवंटित करता है और उन्हें शून्य से प्रारंभ करता है |
free
|
स्मृति के निर्दिष्ट ब्लॉक को प्रणाली में वापस मुक्त करता है |
malloc()
और calloc() के मध्य अंतर
malloc()
एक तर्क लेता है (बाइट्स में आवंटित करने के लिए स्मृति की मात्रा), जबकिcalloc()
दो तर्क लेता है - तत्वों की संख्या और प्रत्येक तत्व का आकार।malloc()
केवल स्मृति आवंटित करता है, जबकिcalloc()
आवंटित क्षेत्र में बाइट को आवंटित और शून्य पर समुच्चय करता है।[11]
उपयोग उदाहरण
स्वत: विस्तार के साथ दस पूर्णांकों की एक सरणी बनाना सी में सीधा है:
int array[10];
तथापि, संकलन समय पर सरणी का आकार तय किया गया है। यदि कोई चर-लंबाई_अरे का उपयोग किए बिना एक समान सरणी को गतिशील रूप से आवंटित करना चाहता है, जो सभी C11 कार्यान्वयनों में समर्थित होने की गारंटित नहीं है, तो निम्न कोड का उपयोग किया जा सकता है:
int *array = malloc(10 * sizeof(int));
यह उन बाइट्स की संख्या की गणना करता है जो दस पूर्णांक स्मृति में कब्जा कर लेते है, फिर अनुरोध करता है कि malloc
से कई बाइट्स और परिणाम को array
नामक सूचक को निर्धारित करें ( सी वाक्य रचना के कारण, कुछ स्थितियों में संकेतक और सरणियों का उपयोग एक दूसरे के रूप में किया जा सकता है)।
क्योंकि malloc
अनुरोध को पूरा करने में सक्षम नहीं हो सकता है, यह एक शून्य सूचक लौटा सकता है और यह जांचने के लिए अच्छा क्रमादेशन अभ्यास है:
int *array = malloc(10 * sizeof(int)); if (array == NULL) { fprintf(stderr, "malloc failed\n"); return -1; }
जब क्रमादेश को गतिशील सरणी की आवश्यकता नहीं होती है, तो उसे मुक्त संग्रह ग्रहण करने वाली स्मृति को वापस करने के लिए कॉल मुक्त करना होगा:
free(array);
malloc
द्वारा अलग की गई स्मृति को प्रारंभ नहीं किया गया है और इसमें क्रॉफ्ट हो सकता है: पहले प्रयोग किए गए और छोड़े गए डेटा के अवशेष। malloc
के साथ आवंटन के बाद, सरणी के तत्व अप्रारंभीकृत चर हैं। आदेश calloc
एक आवंटन लौटाएगा जो पहले ही साफ हो चुका है:
int *array = calloc(10, sizeof(int));
रीयलोक के साथ हम एक सूचक बिंदु की स्मृति की मात्रा का आकार बदल सकते हैं। उदाहरण के लिए, यदि हमारे पास आकार की सरणी के रूप में कार्य करने वाला सूचक है और हम इसे आकार की एक सरणी में बदलना चाहते हैं ,तो हम रीयलोक का उपयोग कर सकते हैं।
int *arr = malloc(2 * sizeof(int)); arr[0] = 1; arr[1] = 2; arr = realloc(arr, 3 * sizeof(int)); arr[2] = 3;
ध्यान दें कि रीयलोक को ब्लॉक का आधार पता बदलना चाहिए (यानी यदि यह मूल ब्लॉक के आकार को बढ़ाने में विफल रहा है, और इसलिए कहीं और एक नया बड़ा ब्लॉक आवंटित किया है और इसमें पुराने विषय की प्रतिलिपि बनाई है)। इसलिए, मूल ब्लॉक के भीतर पतों के लिए कोई संकेतक भी अब मान्य नहीं हैं।
सुरक्षा प्रकार
malloc
एक शून्य सूचक (शून्य*
) देता है, जो इंगित करता है कि यह अज्ञात डेटा प्रकार के क्षेत्र के लिए सूचक है। मजबूत प्रकार की प्रणाली के कारण C++ में कास्ट का उपयोग आवश्यक है, जबकि सी में ऐसा नहीं है। कोई "कास्ट" कर सकता है (प्रकार रूपांतरण देखें) यह सूचक एक विशिष्ट प्रकार के लिए:
int *ptr, *ptr2; ptr = malloc(10 * sizeof(*ptr)); /* without a cast */ ptr2 = (int *)malloc(10 * sizeof(*ptr)); /* with a cast */
ऐसी कास्ट करने के फायदे और नुकसान हैं।
कास्ट करने के फायदे
- कास्ट को सम्मिलित करने से सी क्रमादेश या फलन को C++ के रूप में संकलित करने की अनुमति मिल सकती है।
- कास्ट
malloc
के 1989 के पूर्व के संस्करणों के लिए अनुमति देता है जो मूल रूप से एकchar*
देता है।[12] - कास्टिंग से विकासक को प्रकार के आकार में विसंगतियों की पहचान करने में सहायता मिल सकती है, विशेष रूप से अगर सूचक को
malloc()
कॉल से दूर घोषित किया जाता है (यद्यपि आधुनिक संकलक और स्थिर विश्लेषक कास्ट की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं)।
कास्टिंग करने के नुकसान
- सी मानक के अंतर्गत, कास्ट अनावश्यक है।
- कास्ट जोड़ने से हेडर
stdlib.h
को सम्मिलित करने में विफल हो सकते है, जिसमेंmalloc
के लिए फलन आदिप्ररूप पाया जाता है।[12][13]malloc
के लिए एक आदिप्ररूप की अनुपस्थिति में, C90 मानक के लिए आवश्यक है कि सी संकलक मानता है किmalloc
एकint
देता है। यदि कोई कास्ट नहीं है, तो C90 को नैदानिक की आवश्यकता होती है जब यह पूर्णांक सूचक को निर्दिष्ट किया जाता है; तथापि, कास्ट के साथ, इस निदान का उत्पादन नहीं किया जाएगा, एक बग को छिपाते हुए। कुछ वास्तुकला और डेटा मॉडल पर (जैसे 64-बिट प्रणाली पर LP64, जहांlong
और सूचक्स 64-बिट हैं औरint
32-बिट है), यह त्रुटि वास्तव में अपरिभाषित व्यवहार का परिणाम हो सकती है, क्योंकि निहित रूप से घोषितmalloc
32- रिटर्न देता है। बिट मान जबकि वास्तव में परिभाषित फलन 64-बिट मान लौटाता है। कॉलिंग सम्मेलन और स्मृति लेआउट के आधार पर, इसका परिणाम हीप तोड़ना हो सकता है। आधुनिक संकलकों में इस मुद्दे पर किसी का ध्यान नहीं जाने की संभावना कम है, क्योंकि C99 निहित घोषणाओं की अनुमति नहीं देता है, इसलिए संकलक को निदान का उत्पादन करना चाहिए, भले ही वहint
रिटर्न मान ले। - यदि इसकी घोषणा पर सूचक का प्रकार बदल दिया गया है, तो किसी को भी सभी पंक्तियों को बदलने की आवश्यकता हो सकती है जहां
malloc
को संबोधित और कास्ट किया जाता है।
सामान्य त्रुटियाँ
गतिशील स्मृति आवंटन का अनुचित उपयोग प्रायः बग का स्रोत हो सकता है। इनमें सुरक्षा बग या क्रमादेश क्रैश सम्मिलित हो सकते हैं, जो प्रायः विभाजन दोषों के कारण होते हैं।
सबसे सामान्य त्रुटियां इस प्रकार हैं:[14]
आवंटन विफलताओं की जांच नहीं करना:
स्मृति आवंटन सफल होने की गारंटी नहीं है, और इसके बदले एक शून्य सूचक प्रतिगमन कर सकता है। यदि आबंटन सफल है, तो जाँच किए बिना दिए गए मान का उपयोग करना, अपरिभाषित व्यवहार को आमंत्रित करता है। यह सामान्यतः दुर्घटना की ओर जाता है (नल सूचक विचलन पर परिणामी विभाजन दोष के कारण), लेकिन इस बात की कोई गारंटी नहीं है कि क्रैश होगा इसलिए उस पर भरोसा करने से भी समस्याएँ हो सकती हैं।
स्मृति रिसाव:
मुफ्त का उपयोग करके स्मृति को हटाने में विफलता गैर-पुन: प्रयोज्य स्मृति का निर्माण करती है, जो अब क्रमादेश द्वारा उपयोग नहीं की जाती है। यह स्मृति संसाधनों को असफल करता है और इन संसाधनों के समाप्त होने पर आवंटन विफल हो सकता है।
तार्किक त्रुटियां:
सभी आवंटनों को एक ही प्रतिरूप का पालन करना चाहिए: malloc
का उपयोग करके आवंटन, डेटा संग्रह करने के लिए उपयोग, मुफ्त का उपयोग करके पुनःआवंटन। इस प्रतिरूप का पालन करने में विफलता, जैसे मुफ्त कॉल के बाद स्मृति उपयोग (झूलने वाला सूचक) malloc
(जंगली सूचक) पर कॉल करने से पहले, दो बार free
कॉल करना (दोगुना मुक्त), आदि, सामान्यतः एक विभाजन दोष का कारण बनता है और क्रमादेश के क्रैश होने का परिणाम होता है। ये त्रुटियां क्षणिक और डिबग करने में कठिन हो सकती हैं - उदाहरण के लिए, मुक्त स्मृति को सामान्यतः OS द्वारा तुरंत पुनः प्राप्त नहीं किया जाता है, और इस प्रकार लटकने वाले संकेत थोड़ी देर के लिए बने रह सकते हैं और काम करने लगते हैं।
इसके अतिरिक्त, एएनएसआई सी मानकीकरण से पहले एक अंतरापृष्ठ के रूप में, malloc
और इसके संबंधित कार्यों में ऐसे व्यवहार होते हैं जिन्हें जानबूझकर स्वयं के लिए परिभाषित करने के लिए कार्यान्वयन के लिए छोड़ दिया गया था। उनमें से एक शून्य-लंबाई आवंटन है, जो कि realloc
के साथ अधिक समस्या है क्योंकि यह शून्य का आकार बदलने के लिए अधिक सामान्य है।[15] यद्यपि POSIX और ऐकल यूनिक्स विशिष्टता दोनों को 0-आकार के आवंटन के उचित संचालन की आवश्यकता होती है, या तो NULL
या कुछ और जो सुरक्षित रूप से मुक्त किया जा सकता है,[16] इन नियमों का पालन करने के लिए सभी प्लेटफार्मों की आवश्यकता नहीं है। इसके कारण होने वाली कई डबल-मुक्त त्रुटियों में, 2019 व्हाट्सप्प आरसीई विशेष रूप से प्रमुख था।[17] इन कार्यों को लपेटने की एक शैली उन्हें सुरक्षित बनाने के लिए केवल 0-आकार के आवंटन की जाँच करना और उन्हें आकार 1 में बदलना है। (रिटर्निंग) NULL
इसकी अपनी समस्याएँ हैं: यह अन्यथा एक स्मृति से बाहर विफलता का संकेत देता है। realloc
के मामले में यह संकेत होगा कि मूल स्मृति को स्थानांतरित नहीं किया गया था और मुक्त नहीं किया गया था, जो फिर से आकार 0 के मामले में नहीं है, जिससे दोगुना-मुक्त हो जाता है।)[18]
कार्यान्वयन
स्मृति प्रबंधन का कार्यान्वयन काफी हद तक संचालन प्रणाली और वास्तुकला पर निर्भर करता है। कुछ संचालन प्रणाली मॉलोक के लिए आवंटक की आपूर्ति करते हैं, जबकि अन्य डेटा के कुछ क्षेत्रों को नियंत्रित करने के लिए कार्यों की आपूर्ति करते हैं। एक ही गतिशील स्मृति संभाजक का उपयोग प्रायः malloc
और संचालक दोनों को C++ में लागू करने के लिए किया जाता है।[19]
हीप-आधारित
संभाजक का कार्यान्वयन सामान्यतः हीप स्मृति या डेटा खंड का उपयोग करके किया जाता है। आवंटक सामान्यतः आवंटन अनुरोधों को पूरा करने के लिए हीप का विस्तार और अनुबंध करेगा।
हीप विधि कुछ अंतर्निहित दोषों से ग्रस्त है, जो पूरी तरह से विखंडन से उत्पन्न है। स्मृति आबंटन की किसी भी विधि की तरह, हीप खंडित हो जाएगा; अर्थात्, हीप पर आवंटित स्थान में प्रयुक्त और अप्रयुक्त स्मृति के खंड होंगे। हीप का विस्तार करने का सहारा लेने से पहले एक अच्छा आवंटक उपयोग करने के लिए पहले से आवंटित स्मृति के अप्रयुक्त क्षेत्र को खोजने का प्रयास करेगा। इस पद्धति के साथ प्रमुख समस्या यह है कि हीप में केवल दो महत्वपूर्ण विशेषताएं हैं: आधार, या आभासी स्मृति स्पेस में हीप का आरंभ; और लंबाई, या इसका आकार। हीप को अपनी पूरी लंबाई भरने के लिए पर्याप्त प्रणाली स्मृति की आवश्यकता होती है, और इसका आधार कभी नहीं बदल सकता। इस प्रकार, अप्रयुक्त स्मृति का कोई भी बड़ा क्षेत्र व्यर्थ हो जाता है। हीप इस स्थिति में "अटक" सकता है यदि हीप के अंत में एक छोटा प्रयुक्त खंड अस्तित्व है, जो पता स्थान की किसी भी राशि को व्यर्थ कर सकता है। अक्रिय स्मृति आवंटन योजनाओं पर, जैसे कि प्रायः लिनक्स संचालन प्रणाली में पाए जाते हैं, एक बड़ा हीप अनिवार्य रूप से समकक्ष प्रणाली स्मृति को आरक्षित नहीं करता है; यह केवल पहली बार लिखने के समय ही ऐसा करेगा (गैर-मैप किए गए स्मृति पृष्ठ शून्य पर लौटते हैं)। इसकी ग्रैन्युलैरिटी पृष्ठ आकार पर निर्भर करती है।
डीएलमॉलोक और पीटीमॉलोक
डौग ली ने 1987 में प्रारम्भ होने वाले एक सामान्य-उद्देश्य आवंटक के रूप में सार्वजनिक डोमेन डीएलमॉलोक ("डौग ली का मॉलोक") विकसित किया है। GNU C लाइब्रेरी (glibc) वोल्फ्राम ग्लोगर के पीटीमॉलोक (pthreads malloc) से ली गई है, जो थ्रेडिंग से संबंधित डीएलमॉलोक का एक द्विशाख है।[20][21][22] नवंबर 2019 तक, डीएलमॉलोक का नवीनतम संस्करण अगस्त 2012 से संस्करण 2.8.6 है।[23]
डीएलमॉलोक एक सीमा टैग आवंटक है। हीप पर स्मृति को "हिस्से" के रूप में आवंटित किया जाता है, एक 8-बाइट संरेखित डेटा संरचना जिसमें एक हेडर और प्रयोग करने योग्य स्मृति होती है। आवंटित स्मृति में हिस्से के आकार और उपयोग के झंडे (डोप सदिश के समान) के लिए 8- या 16-बाइट ओवरहेड होता है। अनाबंटित हिस्से उपयोग करने योग्य स्थान क्षेत्र में अन्य मुक्त हिस्से के लिए संकेत को भी संग्रह करते हैं, जिससे 32-बिट प्रणाली पर न्यूनतम हिस्सा आकार 16 बाइट्स और 64-बिट प्रणाली पर 24/32 (संरेखण पर निर्भर करता है) बाइट्स बनते हैं।[21][23]: : 2.8.6, न्यूनतम आवंटित आकार
असंबद्ध स्मृति को समान आकार के "डिब्बे" में समूहीकृत किया जाता है, जिसे हिस्से की दुगुनी-संबद्ध सूची का उपयोग करके कार्यान्वित किया जाता है (हिस्से के अंदर असंबद्ध स्थान में संग्रहीत संकेत के साथ)। डिब्बे आकार के आधार पर तीन वर्गों में क्रमबद्ध गए हैं:[21][23]: ओवरलेड डेटा संरचना
- 256 बाइट्स ("स्मॉलबिन" अनुरोध) से नीचे के अनुरोधों के लिए, एक साधारण दो शक्ति श्रेष्ठतम आसंजन संभाजक का उपयोग किया जाता है। यदि उस बिन में कोई मुक्त ब्लॉक नहीं है, तो अगले उच्चतम बिन से एक ब्लॉक दो भागों में विभाजित हो जाता है।
- 256 बाइट्स या उससे ऊपर के अनुरोधों के लिए, लेकिन mmap देहली के नीचे, v2.8.0 के बाद से डीएलमॉलोक स्वस्थाने बिटवाइज़ ट्राई कलनविधीय ("ट्रीबिन") का उपयोग करता है। यदि अनुरोध को पूरा करने के लिए कोई खाली स्थान नहीं बचा है, तो सामान्यतः brk प्रणाली कॉल के माध्यम से हीप के आकार को बढ़ाने की प्रयत्न करता है। यह सुविधा पीटीमॉलोक (v2.7.x से) बनने के बाद प्रस्तावित की गई थी, और इसके परिणामस्वरूप यह glibc का हिस्सा नहीं है, जो पुराने सबसे फिट आवंटक को विरासत में मिला है।
- एमएमएपी थ्रेसहोल्ड ("लार्जबिन" अनुरोध) से ऊपर के अनुरोधों के लिए, स्मृति हमेशा एमएमएपी प्रणाली कॉल का उपयोग करके आवंटित की जाती है। थ्रेसहोल्ड सामान्यतः 256 KB है।[24] एमएमएपी प्रणाली बड़े बफ़र्स के साथ उनकी समाप्ति के बाद अंत में एक छोटे से आवंटन को फंसाने की समस्या को टालती है, लेकिन हमेशा स्मृति के एक पूरे पृष्ठ को आवंटित करती है, जो कई वास्तुकला पर आकार में 4096 बाइट्स है।[25]
खेल विकसक एड्रियन स्टोन का तर्क है कि dlmalloc
, एक सीमा-टैग आवंटक के रूप में, कंसोल प्रणाली के लिए अमित्र है जिसमें आभासी स्मृति है लेकिन मांग पृष्ठन नहीं है। ऐसा इसलिए है क्योंकि इसके पूल-सिकुड़ते और बढ़ते कॉलबैक (सिसालोक/सिस्ट्रिम) का उपयोग आभासी स्मृति के अलग-अलग पृष्ठ को आवंटित करने और समर्पण करने के लिए नहीं किया जा सकता है। मांग पृष्ठन के अभाव में विखंडन एक बड़ी चिंता बन जाता है।[26]
FreeBSD's और NetBSD's jemalloc
FreeBSD 7.0 और NetBSD 5.0 के बाद से, पुराने malloc
कार्यान्वयन (पॉल-हेनिंग कैंप द्वारा phkmalloc) को जेसन इवांस द्वारा लिखित jemalloc द्वारा प्रतिस्थापित किया गया था। इसका मुख्य कारण बहु सूत्रण के संबंध में phkmalloc की मापनीयता की कमी थी। लॉक विवाद से बचने के लिए, jemalloc प्रत्येक सीपीयू के लिए अलग "एरेनास" का उपयोग करता है। बहु सूत्रण अनुप्रयोग में प्रति सेकंड आवंटन की संख्या को मापने वाले प्रयोगों से पता चला है कि यह इसे थ्रेड्स की संख्या के साथ रैखिक रूप से पैमाना करता है, जबकि phkmalloc और डीएलमॉलोक दोनों के लिए प्रदर्शन थ्रेड्स की संख्या के व्युत्क्रमानुपाती था।[27]
ओपनबीएसडी का मॉलोक
malloc
फलन के ओपनबीएसडी का कार्यान्वयन एमएमएपी का उपयोग करता है। एक पृष्ठ से बड़े आकार के अनुरोधों के लिए, संपूर्ण आवंटन mmap
का उपयोग करके पुनर्प्राप्त किया जाता है; कई "बाल्टी पृष्ठों" के भीतर, malloc
द्वारा अनुरक्षित स्मृति पूल से छोटे आकार निर्दिष्ट किए जाते हैं, जिन्हें एमएमएपी के साथ भी आवंटित किया जाता है।[28][better source needed] मुक्त करने के लिए एक कॉल पर, स्मृति को जारी किया जाता है और मुनमैप का उपयोग करके प्रक्रिया पता स्थान से munmap
किया जाता है। इस प्रणाली को ओपनबीएसडी के हिस्से के रूप में कार्यान्वित एड्रेस स्पेस लेआउट रैंडमाइजेशन और गैप पेज सुविधाओं का लाभ उठाकर सुरक्षा में सुधार करने के लिए डिज़ाइन किया गया है। mmap
प्रणाली कॉल, और उपयोग-बाद-मुक्त बग का पता लगाने के लिए- चूंकि एक बड़ी स्मृति आवंटन मुक्त होने के बाद पूरी तरह से मैप नहीं किया गया है, आगे के उपयोग से विभाजन की गलती और क्रमादेश की समाप्ति का कारण बनता है।
होर्ड मॉलोक
होर्ड एक संभाजक है जिसका लक्ष्य स्केलेबल स्मृति आवंटन प्रदर्शन है। OpenBSD के संभाजक की तरह, होर्ड उपयोग करता है mmap
विशेष रूप से, लेकिन सुपरब्लॉक कहे जाने वाले 64 किलोबाइट के टुकड़ों में स्मृति का प्रबंधन करता है। होर्ड के हीप को तार्किक रूप से एक ग्लोबल हीप और कई प्रति-प्रोसेसर हीप में विभाजित किया गया है। इसके अलावा, एक थ्रेड-लोकल कैश है जो सीमित संख्या में सुपरब्लॉक रख सकता है। स्थानीय प्रति-थ्रेड या प्रति-प्रोसेसर हीप पर केवल सुपरब्लॉक से आवंटित करके, और ज्यादातर खाली सुपरब्लॉक को ग्लोबल हीप में ले जाकर अन्य प्रोसेसर द्वारा पुन: उपयोग किया जा सकता है, थ्रेड्स की संख्या के साथ रैखिक मापनीयता प्राप्त करते समय होर्ड विखंडन को कम रखता है .[29]
मिमललोक
प्रदर्शन पर ध्यान देने के साथ माइक्रोसॉफ्ट रिसर्च से एक खुला स्त्रोत | ओपन-सोर्स कॉम्पैक्ट सामान्य-उद्देश्य स्मृति संभाजक।[30] लाइब्रेरी कोड की लगभग 11,000 पंक्तियाँ हैं।
थ्रेड-कैशिंग मॉलोक (tcmalloc)
छोटे आवंटन के लिए प्रत्येक थ्रेड में थ्रेड-लोकल स्टोरेज होता है। बड़े आवंटन के लिए mmap या sbrk का उपयोग किया जा सकता है। TCMalloc, Google द्वारा विकसित एक malloc,[31] मृत धागे के स्थानीय भंडारण के लिए कचरा संग्रह है। TCMalloc को बहुप्रचारित क्रमादेशों के लिए glibc के पीटीमॉलोक से दुगने से भी अधिक तेज़ माना जाता है।[32][33]
इन-कर्नेल
संचालन प्रणाली कर्नेल (कंप्यूटर साइंस) को एप्लिकेशन क्रमादेश की तरह ही स्मृति आवंटित करने की आवश्यकता होती है। का कार्यान्वयन malloc
तथापि, कर्नेल के भीतर प्रायः सी लाइब्रेरीों द्वारा उपयोग किए जाने वाले कार्यान्वयन से काफी भिन्न होता है। उदाहरण के लिए, स्मृति बफ़र्स को प्रत्यक्ष स्मृति एक्सेस द्वारा लगाए गए विशेष प्रतिबंधों के अनुरूप होने की आवश्यकता हो सकती है, या स्मृति आवंटन फलन को इंटरप्ट संदर्भ से कॉल किया जा सकता है।[34] यह एक की आवश्यकता है malloc
कार्यान्वयन संचालन प्रणाली कर्नेल के आभासी स्मृति सबप्रणाली के साथ कसकर एकीकृत है।
मॉलोक ओवरराइडिंग
क्योंकि malloc
और उसके रिश्तेदार किसी क्रमादेश के प्रदर्शन पर गहरा प्रभाव डाल सकते हैं, एप्लिकेशन के आवंटन प्रतिरूप के लिए अनुकूलित किए गए कस्टम कार्यान्वयन द्वारा किसी विशिष्ट एप्लिकेशन के कार्यों को ओवरराइड करना असामान्य नहीं है। सी मानक ऐसा करने का कोई तरीका प्रदान नहीं करता है, लेकिन संचालन प्रणाली ने गतिशील लिंकिंग का फायदा उठाकर ऐसा करने के कई तरीके खोजे हैं। प्रतीकों को ओवरराइड करने के लिए एक तरीका केवल एक अलग लाइब्रेरी में लिंक करना है। एक अन्य, UNIX System V#SVR3|Unix System V.3 द्वारा नियोजित, बनाना है malloc
और free
फलन सूचक्स जो एक एप्लिकेशन कस्टम प्रकार्य पर रीसेट कर सकता है।[35]
POSIX-जैसी प्रणालियों पर सबसे आम रूप पर्यावरण चर LD_PRELOAD को आवंटक के पथ के साथ सेट करना है, ताकि गतिशील लिंकर libc कार्यान्वयन के बजाय malloc/calloc/free के उस संस्करण का उपयोग करे।
आवंटन आकार सीमा
सबसे बड़ा संभव स्मृति ब्लॉक malloc
आवंटित कर सकते हैं मेजबान प्रणाली पर निर्भर करता है, विशेष रूप से भौतिक स्मृति का आकार और संचालन प्रणाली कार्यान्वयन।
सैद्धांतिक रूप से, सबसे बड़ी संख्या वह अधिकतम मान होना चाहिए जिसे a में रखा जा सकता है size_t
प्रकार, जो एक कार्यान्वयन-निर्भर अहस्ताक्षरित पूर्णांक है जो स्मृति के क्षेत्र के आकार का प्रतिनिधित्व करता है। C99 मानक में और बाद में, यह के रूप में उपलब्ध है SIZE_MAX
से लगातार <stdint.h>
. तथापि इसकी गारंटी नहीं है ISO C, यह सामान्यतः है 2^(CHAR_BIT * sizeof(size_t)) - 1
.
ग्लिबैक प्रणाली पर, सबसे बड़ा संभावित स्मृति ब्लॉक malloc
आवंटित कर सकते हैं केवल इस आकार का आधा है, अर्थात् 2^(CHAR_BIT * sizeof(ptrdiff_t) - 1) - 1
.[36]
एक्सटेंशन और विकल्प
सी लाइब्रेरी कार्यान्वयन विभिन्न संचालन प्रणाली और संकलक्स के साथ मानक के विकल्प और एक्सटेंशन के साथ आ सकता है malloc
इंटरफेस। इनमें से उल्लेखनीय है:
alloca
, जो कॉल स्टैक पर बाइट्स की अनुरोधित संख्या आवंटित करता है। कोई संबंधित डीलोकेशन फलन मौजूद नहीं है, क्योंकि सामान्यतः कॉलिंग फलन के वापस आते ही स्मृति को हटा दिया जाता है।alloca
UNIX/32V|32/V (1978) से ही यूनिक्स प्रणाली पर मौजूद था, लेकिन इसका उपयोग कुछ (जैसे, एम्बेडेड) संदर्भों में समस्याग्रस्त हो सकता है।[37] जबकि कई संकलकों द्वारा समर्थित है, यह एएनएसआई सी | एएनएसआई-सी मानक का हिस्सा नहीं है और इसलिए हमेशा पोर्टेबल नहीं हो सकता है। इससे मामूली प्रदर्शन समस्याएं भी हो सकती हैं: यह चर-आकार के स्टैक फ़्रेमों की ओर ले जाती है, ताकि दोनों कॉल स्टैक#STACK-POINTER को प्रबंधित करने की आवश्यकता हो (निश्चित आकार के स्टैक फ़्रेमों के साथ, इनमें से एक बेमानी है)।[38] बड़े आवंटन से स्टैक ओवरफ़्लो के कारण अपरिभाषित व्यवहार का जोखिम भी बढ़ सकता है।[39] C99 ने वैकल्पिक हीप आवंटन तंत्र के रूप में चर-लंबाई सरणियों की पेशकश की – हालाँकि, इस सुविधा को बाद के C11 (C मानक संशोधन) मानक में वैकल्पिक कर दिया गया था।- POSIX एक फलन को परिभाषित करता है
posix_memalign
जो कॉलर-निर्दिष्ट संरेखण के साथ स्मृति आवंटित करता है। इसका आवंटन विलोपित किया गया हैfree
,[40] इसलिए कार्यान्वयन को सामान्यतः मॉलोक लाइब्रेरी का हिस्सा होना चाहिए।
यह भी देखें
संदर्भ
- ↑ 1.0 1.1 7.20.3 Memory management functions (PDF). p. 313.
{{cite book}}
:|work=
ignored (help) - ↑ Summit, Steve. "Chapter 11: Memory Allocation". C Programming Notes. Retrieved 2020-07-11.
- ↑ "aligned_alloc(3) - Linux man page".
- ↑ Stroustrup, Bjarne (2008). Programming: Principles and Practice Using C++. Addison Wesley. p. 1009. ISBN 978-0-321-54372-1.
- ↑ "gcc manual". gnu.org. Retrieved 2008-12-14.
- ↑ Brian W. Kernighan, Dennis M. Ritchie, The C Programming Language, Prentice-Hall, 1978; Section 7.9 (page 156) describes
calloc
andcfree
, and Section 8.7 (page 173) describes an implementation foralloc
andfree
. - ↑ Version 6 Unix Programmer's Manual –
- ↑ Version 7 Unix Programmer's Manual –
- ↑ Anonymous, Unix Programmer's Manual, Vol. 1, Holt Rinehart and Winston, 1983 (copyright held by Bell Telephone Laboratories, 1983, 1979); The
man
page formalloc
etc. is given on page 275. - ↑ FreeBSD Library Functions Manual –
- ↑ Linux Programmer's Manual – Library Functions –
- ↑ 12.0 12.1 "कास्टिंग मॉलोक". Cprogramming.com. Retrieved 2007-03-09.</रेफरी>
- कास्टिंग से डेवलपर को प्रकार के आकार में विसंगतियों की पहचान करने में मदद मिल सकती है, यदि गंतव्य सूचक प्रकार में परिवर्तन होता है, खासकर यदि सूचक को दूर घोषित किया गया हो
malloc()
कॉल (हालांकि आधुनिक संकलक और स्थिर विश्लेषक कलाकारों की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं<ref>"clang: lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp Source File". clang.llvm.org. Retrieved 2018-04-01.
- कास्टिंग से डेवलपर को प्रकार के आकार में विसंगतियों की पहचान करने में मदद मिल सकती है, यदि गंतव्य सूचक प्रकार में परिवर्तन होता है, खासकर यदि सूचक को दूर घोषित किया गया हो
- ↑ "comp.lang.c FAQ list · Question 7.7b". C-FAQ. Retrieved 2007-03-09.
- ↑ Reek, Kenneth (1997-08-04). Pointers on C (in English) (1 ed.). Pearson. ISBN 9780673999863.
- ↑ "MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence". wiki.sei.cmu.edu.
- ↑ "POSIX.1-2017: malloc". pubs.opengroup.org. Retrieved 2019-11-29.
- ↑ Awakened (2019-10-02). "How a double-free bug in WhatsApp turns to RCE". Retrieved 2019-11-29.
- ↑ Felker, Rich [@RichFelker] (2019-10-03). "Wow. The WhatsApp RCE was the wrong behavior for realloc(p,0) so many implementations insist on" (Tweet). Retrieved 2022-08-06 – via Twitter.
- ↑ Alexandrescu, Andrei (2001). Modern C++ Design: Generic Programming and Design Patterns Applied. Addison-Wesley. p. 78.
- ↑ "Wolfram Gloger's malloc homepage". malloc.de. Retrieved 2018-04-01.
- ↑ 21.0 21.1 21.2 Kaempf, Michel (2001). "Vudo malloc tricks". Phrack (57): 8. Archived from the original on 2009-01-22. Retrieved 2009-04-29.
- ↑ "Glibc: Malloc Internals". sourceware.org Trac. Retrieved 2019-12-01.
- ↑ 23.0 23.1 23.2 Lee, Doug. "A Memory Allocator". Retrieved 2019-12-01. HTTP for Source Code
- ↑ "Malloc Tunable Parameters". GNU. Retrieved 2009-05-02.
- ↑ Sanderson, Bruce (2004-12-12). "RAM, Virtual Memory, Pagefile and all that stuff". Microsoft Help and Support.
- ↑ Stone, Adrian. "The Hole That dlmalloc Can't Fill". Game Angst. Retrieved 2019-12-01.
- ↑ Evans, Jason (2006-04-16). "A Scalable Concurrent malloc(3) Implementation for FreeBSD" (PDF). Retrieved 2012-03-18.
- ↑ "libc/stdlib/malloc.c". BSD Cross Reference, OpenBSD src/lib/.
- ↑ Berger, E. D.; McKinley, K. S.; Blumofe, R. D.; Wilson, P. R. (November 2000). Hoard: A Scalable Memory Allocator for Multithreaded Applications (PDF). ASPLOS-IX. Proceedings of the ninth international conference on Architectural support for programming languages and operating systems. pp. 117–128. CiteSeerX 10.1.1.1.4174. doi:10.1145/378993.379232. ISBN 1-58113-317-0.
- ↑ Microsoft releases optimized malloc() as open source - Slashdot
- ↑ TCMalloc homepage
- ↑ Ghemawat, Sanjay; Menage, Paul; TCMalloc : Thread-Caching Malloc
- ↑ Callaghan, Mark (2009-01-18). "High Availability MySQL: Double sysbench throughput with TCMalloc". Mysqlha.blogspot.com. Retrieved 2011-09-18.
- ↑ "kmalloc()/kfree() include/linux/slab.h". People.netfilter.org. Retrieved 2011-09-18.
- ↑ Levine, John R. (2000) [October 1999]. "Chapter 9: Shared libraries". Linkers and Loaders. The Morgan Kaufmann Series in Software Engineering and Programming (1 ed.). San Francisco, USA: Morgan Kaufmann. ISBN 1-55860-496-0. OCLC 42413382. Archived from the original on 2012-12-05. Retrieved 2020-01-12. Code: [1][2] Errata: [3]
- ↑ "malloc: make malloc fail with requests larger than PTRDIFF_MAX". Sourceware Bugzilla. 2019-04-18. Retrieved 2020-07-30.
- ↑ "Why is the use of alloca() not considered good practice?". stackoverflow.com. Retrieved 2016-01-05.
- ↑ Amarasinghe, Saman; Leiserson, Charles (2010). "6.172 Performance Engineering of Software Systems, Lecture 10". MIT OpenCourseWare. Massachusetts Institute of Technology. Archived from the original on 2015-06-22. Retrieved 2015-01-27.
- ↑ "alloca(3) - Linux manual page". man7.org. Retrieved 2016-01-05.
- ↑ The Single UNIX Specification, Version 4 from The Open Group – System Interfaces Reference,
बाहरी संबंध
- Definition of malloc in IEEE Std 1003.1 standard
- Lea, Doug; The design of the basis of the glibc allocator
- Gloger, Wolfram; The पीटीमॉलोक homepage
- Berger, Emery; The Hoard homepage
- Douglas, Niall; The nedmalloc homepage
- Evans, Jason; The jemalloc homepage
- Google; The tcmalloc homepage
- Simple Memory Allocation Algorithms on OSDEV Community
- Michael, Maged M.; Scalable Lock-Free Dynamic Memory Allocation
- Bartlett, Jonathan; Inside memory management – The choices, tradeoffs, and implementations of dynamic allocation
- Memory Reduction (GNOME) wiki page with much information about fixing malloc
- C99 standard draft, including TC1/TC2/TC3
- Some useful references about C
- ISO/IEC 9899 – Programming languages – C
- Understanding glibc malloc