सी गतिशील स्मृति आवंटन: Difference between revisions

From Vigyanwiki
(TEXT)
(TEXT)
Line 87: Line 87:
* कास्ट को सम्मिलित करने से सी क्रमादेश या फलन को C++ के रूप में संकलित करने की अनुमति मिल सकती है।
* कास्ट को सम्मिलित करने से सी क्रमादेश या फलन को C++ के रूप में संकलित करने की अनुमति मिल सकती है।
* कास्ट  <code>malloc</code> के 1989 के पूर्व के संस्करणों के लिए अनुमति देता है जो मूल रूप से एक <code>char*</code>देता है।<ref name="Cprog_malloc">{{cite web |url=http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1047673478 |title=कास्टिंग मॉलोक|publisher=Cprogramming.com |access-date=9 March 2007 }}</रेफरी>
* कास्ट  <code>malloc</code> के 1989 के पूर्व के संस्करणों के लिए अनुमति देता है जो मूल रूप से एक <code>char*</code>देता है।<ref name="Cprog_malloc">{{cite web |url=http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1047673478 |title=कास्टिंग मॉलोक|publisher=Cprogramming.com |access-date=9 March 2007 }}</रेफरी>
*कास्टिंग से डेवलपर को प्रकार के आकार में विसंगतियों की पहचान करने में मदद मिल सकती है, यदि गंतव्य सूचक प्रकार में परिवर्तन होता है, खासकर यदि सूचक को दूर घोषित किया गया हो <code>malloc()</code> कॉल (हालांकि आधुनिक संकलक और स्थिर विश्लेषक कलाकारों की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं<nowiki><ref></nowiki>{{cite web|url=http://clang.llvm.org/doxygen/MallocSizeofChecker_8cpp_source.html|title=clang: lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp Source File|website=clang.llvm.org|access-date=1 April 2018}}</ref>  
*कास्टिंग से डेवलपर को प्रकार के आकार में विसंगतियों की पहचान करने में मदद मिल सकती है, यदि गंतव्य सूचक प्रकार में परिवर्तन होता है, खासकर यदि सूचक को दूर घोषित किया गया हो <code>malloc()</code> कॉल (हालांकि आधुनिक संकलक और स्थिर विश्लेषक कलाकारों की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं<nowiki><ref></nowiki>{{cite web|url=http://clang.llvm.org/doxygen/MallocSizeofChecker_8cpp_source.html|title=clang: lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp Source File|website=clang.llvm.org|access-date=1 April 2018}}</ref>
*कास्टिंग से विकासक को प्रकार के आकार में विसंगतियों की पहचान करने में सहायता मिल सकती है, विशेष रूप से अगर सूचक को<code>malloc()</code>कॉल से दूर घोषित किया जाता है (यद्यपि आधुनिक संकलक और स्थिर विश्लेषक कास्ट की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं)।
*कास्टिंग से विकासक को प्रकार के आकार में विसंगतियों की पहचान करने में सहायता मिल सकती है, विशेष रूप से अगर सूचक को<code>malloc()</code>कॉल से दूर घोषित किया जाता है (यद्यपि आधुनिक संकलक और स्थिर विश्लेषक कास्ट की आवश्यकता के बिना इस तरह के व्यवहार पर चेतावनी दे सकते हैं)।


=== कास्टिंग करने के नुकसान ===
=== कास्टिंग करने के नुकसान ===
* सी मानक के तहत, कास्ट बेमानी है।
* सी मानक के अंतर्गत, कास्ट अनावश्यक है।
* कास्ट जोड़ने से शीर्षलेख सम्मिलित करने में विफल हो सकता है <code>stdlib.h</code>, जिसमें [[फ़ंक्शन प्रोटोटाइप|फलन प्रोटोटाइप]] के लिए <code>malloc</code> पाया जाता है।<ref name="Cprog_malloc" /><ref>{{cite web |url=http://www.c-faq.com/malloc/mallocnocast.html |title=comp.lang.c FAQ list · Question 7.7b |publisher=C-FAQ |access-date=9 March 2007 }}</ref> के लिए एक प्रोटोटाइप के अभाव में <code>malloc</code>, C90 मानक के लिए आवश्यक है कि C संकलक मान ले <code>malloc</code> एक देता है <code>int</code>. यदि कोई कास्ट नहीं है, तो C90 को डायग्नोस्टिक की आवश्यकता होती है जब यह पूर्णांक सूचक को सौंपा जाता है; तथापि, कलाकारों के साथ, इस निदान का उत्पादन नहीं किया जाएगा, एक बग को छिपाते हुए। कुछ आर्किटेक्चर और डेटा मॉडल पर (जैसे 64-बिट प्रणाली पर LP64, जहां <code>long</code> और सूचक्स 64-बिट हैं और <code>int</code> 32-बिट है), यह त्रुटि वास्तव में अपरिभाषित व्यवहार का परिणाम हो सकती है, जैसा कि स्पष्ट रूप से घोषित किया गया है <code>malloc</code> 32-बिट मान लौटाता है जबकि वास्तव में परिभाषित फलन 64-बिट मान लौटाता है। कॉलिंग कन्वेंशन और स्मृति लेआउट के आधार पर, इसका परिणाम [[ढेर तोड़ना]] हो सकता है। आधुनिक संकलकों में इस मुद्दे पर किसी का ध्यान नहीं जाने की संभावना कम है, क्योंकि C99 निहित घोषणाओं की अनुमति नहीं देता है, इसलिए संकलक को डायग्नोस्टिक का उत्पादन करना चाहिए, भले ही वह मान ले <code>int</code> वापस करना।
* कास्ट जोड़ने से हेडर <code>stdlib.h</code> को सम्मिलित करने में विफल हो सकते है, जिसमें <code>malloc</code> के लिए [[फ़ंक्शन प्रोटोटाइप|फलन आदिप्ररूप]] पाया जाता है।<ref name="Cprog_malloc" /><ref>{{cite web |url=http://www.c-faq.com/malloc/mallocnocast.html |title=comp.lang.c FAQ list · Question 7.7b |publisher=C-FAQ |access-date=9 March 2007 }}</ref> <code>malloc</code> के लिए एक आदिप्ररूप की अनुपस्थिति में, C90 मानक के लिए आवश्यक है कि सी संकलक मानता है कि <code>malloc</code> एक <code>int</code> देता है। यदि कोई कास्ट नहीं है, तो C90 को नैदानिक की आवश्यकता होती है जब यह पूर्णांक सूचक को निर्दिष्‍ट किया जाता है; तथापि, कास्ट के साथ, इस निदान का उत्पादन नहीं किया जाएगा, एक बग को छिपाते हुए। कुछ वास्तुकला और डेटा मॉडल पर (जैसे 64-बिट प्रणाली पर LP64, जहां <code>long</code> और सूचक्स 64-बिट हैं और <code>int</code> 32-बिट है), यह त्रुटि वास्तव में अपरिभाषित व्यवहार का परिणाम हो सकती है, क्योंकि निहित रूप से घोषित <code>malloc</code>32- रिटर्न देता है। बिट मान जबकि वास्तव में परिभाषित फलन 64-बिट मान लौटाता है। कॉलिंग सम्मेलन और स्मृति लेआउट के आधार पर, इसका परिणाम [[ढेर तोड़ना]] हो सकता है। आधुनिक संकलकों में इस मुद्दे पर किसी का ध्यान नहीं जाने की संभावना कम है, क्योंकि C99 निहित घोषणाओं की अनुमति नहीं देता है, इसलिए संकलक को निदान का उत्पादन करना चाहिए, भले ही वह <code>int</code> रिटर्न मान ले।
* यदि इसकी घोषणा पर सूचक का प्रकार बदल दिया गया है, तो किसी को भी सभी पंक्तियों को बदलने की आवश्यकता हो सकती है <code>malloc</code> बुलाया और डाला जाता है।
* यदि इसकी घोषणा पर सूचक का प्रकार बदल दिया गया है, तो किसी को भी सभी पंक्तियों को बदलने की आवश्यकता हो सकती है जहां <code>malloc</code> को संबोधित और कास्ट किया जाता है।


== सामान्य त्रुटियाँ ==
== सामान्य त्रुटियाँ ==
गतिशील स्मृति आवंटन का अनुचित उपयोग अक्सर बग का स्रोत हो सकता है। इनमें सुरक्षा बग या क्रमादेश क्रैश सम्मिलित हो सकते हैं, जो अक्सर सेगमेंटेशन दोषों के कारण होते हैं।
गतिशील स्मृति आवंटन का अनुचित उपयोग प्रायः बग का स्रोत हो सकता है। इनमें सुरक्षा बग या क्रमादेश क्रैश सम्मिलित हो सकते हैं, जो प्रायः विभाजन दोषों के कारण होते हैं।


सबसे आम त्रुटियां इस प्रकार हैं:<ref>{{Cite book|title=Pointers on C|last=Reek|first=Kenneth|date=1997-08-04|publisher=Pearson|isbn=9780673999863|edition=1|language=en}}</ref>
सबसे सामान्य त्रुटियां इस प्रकार हैं:<ref>{{Cite book|title=Pointers on C|last=Reek|first=Kenneth|date=1997-08-04|publisher=Pearson|isbn=9780673999863|edition=1|language=en}}</ref>
आवंटन विफलताओं की जांच नहीं करना: स्मृति आवंटन सफल होने की गारंटी नहीं है, और इसके बजाय एक शून्य सूचक लौटा सकता है। यदि आबंटन सफल है, तो जाँच किए बिना दिए गए मान का उपयोग करना, [[अपरिभाषित व्यवहार]] को आमंत्रित करता है। यह सामान्यतः दुर्घटना की ओर जाता है (नल सूचक डिरेफरेंस पर परिणामी विभाजन दोष के कारण), लेकिन इस बात की कोई गारंटी नहीं है कि क्रैश होगा इसलिए उस पर भरोसा करने से भी समस्याएँ हो सकती हैं।
स्मृति लीक: स्मृति का उपयोग करने में विफलता <code>free</code> गैर-पुन: प्रयोज्य स्मृति का निर्माण होता है, जो अब क्रमादेश द्वारा उपयोग नहीं किया जाता है। यह स्मृति संसाधनों को बर्बाद करता है और इन संसाधनों के समाप्त होने पर आवंटन विफल हो सकता है। {{anchor|Use after free}}
तार्किक त्रुटियां: सभी आवंटनों को एक ही पैटर्न का पालन करना चाहिए: आवंटन का उपयोग करना <code>malloc</code>, डेटा स्टोर करने के लिए उपयोग, डीलोकेशन का उपयोग करना <code>free</code>. इस पैटर्न का पालन करने में विफलता, जैसे कॉल करने के बाद स्मृति उपयोग <code>free</code> (झूलने वाला सूचक) या कॉल करने से पहले <code>malloc</code> ([[जंगली सूचक]]), बुला रहा है <code>free</code> दो बार (डबल मुक्त), आदि, सामान्यतः एक विभाजन दोष का कारण बनता है और क्रमादेश के क्रैश होने का परिणाम होता है। ये त्रुटियां क्षणिक और डिबग करने में कठिन हो सकती हैं - उदाहरण के लिए, मुक्त स्मृति को सामान्यतः OS द्वारा तुरंत पुनः प्राप्त नहीं किया जाता है, और इस प्रकार लटकने वाले सूचक्स थोड़ी देर के लिए बने रह सकते हैं और काम करने लगते हैं।


इसके अलावा, एएनएसआई सी मानकीकरण से पहले एक इंटरफ़ेस के रूप में, {{code|malloc}} और इसके संबंधित कार्यों में ऐसे व्यवहार होते हैं जिन्हें जानबूझकर स्वयं के लिए परिभाषित करने के लिए कार्यान्वयन के लिए छोड़ दिया गया था। उनमें से एक शून्य-लंबाई आवंटन है, जो कि अधिक समस्या है {{code|realloc}} चूंकि शून्य का आकार बदलना अधिक सामान्य है।<ref>{{cite web |title=MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence |url=https://wiki.sei.cmu.edu/confluence/display/c/MEM04-C.+Beware+of+zero-length+allocations |website=wiki.sei.cmu.edu}}<!-- Note: the example is bullshit. Freeing NULL is safe because it does nothing. --></ref> हालाँकि [[POSIX]] और सिंगल यूनिक्स विशिष्टता दोनों को वापस लौटकर 0-आकार के आवंटन के उचित प्रबंधन की आवश्यकता होती है {{code|NULL}} या कुछ और जिसे सुरक्षित रूप से मुक्त किया जा सकता है,<ref>{{cite web |title=POSIX.1-2017: malloc |url=https://pubs.opengroup.org/onlinepubs/9699919799/ |website=pubs.opengroup.org |access-date=29 November 2019}}</ref> सभी प्लेटफॉर्म के लिए इन नियमों का पालन करना आवश्यक नहीं है। इसके कारण होने वाली कई डबल-मुक्त त्रुटियों में, 2019 [[व्हाट्सप्प]] आरसीई विशेष रूप से प्रमुख था।<ref>{{cite web |last1=Awakened |title=How a double-free bug in WhatsApp turns to RCE |date=2 October 2019 |url=https://awakened1712.github.io/hacking/hacking-whatsapp-gif-rce/ |access-date=29 November 2019}}</ref> इन कार्यों को लपेटने का एक तरीका उन्हें सुरक्षित बनाने के लिए केवल 0-आकार के आवंटन की जाँच करना और उन्हें आकार 1 में बदलना है। (रिटर्निंग) {{code|NULL}} इसकी अपनी समस्याएँ हैं: यह अन्यथा एक आउट-ऑफ़-स्मृति विफलता का संकेत देता है। के मामले में {{code|realloc}} यह संकेत देगा कि मूल स्मृति को स्थानांतरित और मुक्त नहीं किया गया था, जो फिर से आकार 0 के मामले में नहीं है, जिससे डबल-मुक्त हो जाता है।)<ref>{{cite tweet |last1=Felker |first1=Rich |title=Wow. The WhatsApp RCE was the wrong behavior for realloc(p,0) so many implementations insist on. |user=RichFelker |number=1179701167569416192 |access-date=6 August 2022 |date=3 October 2019}}</ref>
==== आवंटन विफलताओं की जांच नहीं करना: ====
स्मृति आवंटन सफल होने की गारंटी नहीं है, और इसके बदले एक शून्य सूचक प्रतिगमन कर सकता है। यदि आबंटन सफल है, तो जाँच किए बिना दिए गए मान का उपयोग करना, [[अपरिभाषित व्यवहार]] को आमंत्रित करता है। यह सामान्यतः दुर्घटना की ओर जाता है (नल सूचक विचलन पर परिणामी विभाजन दोष के कारण), लेकिन इस बात की कोई गारंटी नहीं है कि क्रैश होगा इसलिए उस पर भरोसा करने से भी समस्याएँ हो सकती हैं।
 
==== स्मृति रिसाव: ====
मुफ्त का उपयोग करके स्मृति को हटाने में विफलता गैर-पुन: प्रयोज्य स्मृति का निर्माण करती है, जो अब क्रमादेश द्वारा उपयोग नहीं की जाती है। यह स्मृति संसाधनों को असफल  करता है और इन संसाधनों के समाप्त होने पर आवंटन विफल हो सकता है।
 
==== तार्किक त्रुटियां: ====
सभी आवंटनों को एक ही प्रतिरूप का पालन करना चाहिए: <code>malloc</code>का उपयोग करके आवंटन, डेटा संग्रह करने के लिए उपयोग, मुफ्त का उपयोग करके पुनःआवंटन। इस प्रतिरूप का पालन करने में विफलता, जैसे मुफ्त कॉल के बाद स्मृति उपयोग (झूलने वाला सूचक) <code>malloc</code> ([[जंगली सूचक]]) पर कॉल करने से पहले, दो बार <code>free</code> कॉल करना (दोगुना मुक्त), आदि, सामान्यतः एक विभाजन दोष का कारण बनता है और क्रमादेश के क्रैश होने का परिणाम होता है। ये त्रुटियां क्षणिक और डिबग करने में कठिन हो सकती हैं - उदाहरण के लिए, मुक्त स्मृति को सामान्यतः OS द्वारा तुरंत पुनः प्राप्त नहीं किया जाता है, और इस प्रकार लटकने वाले संकेत थोड़ी देर के लिए बने रह सकते हैं और काम करने लगते हैं।
 
इसके अतिरिक्त, एएनएसआई सी मानकीकरण से पहले एक अंतरापृष्ठ के रूप में, {{code|malloc}} और इसके संबंधित कार्यों में ऐसे व्यवहार होते हैं जिन्हें जानबूझकर स्वयं के लिए परिभाषित करने के लिए कार्यान्वयन के लिए छोड़ दिया गया था। उनमें से एक शून्य-लंबाई आवंटन है, जो कि {{code|realloc}} के साथ अधिक समस्या है क्योंकि यह शून्य का आकार बदलने के लिए अधिक सामान्य है।<ref>{{cite web |title=MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence |url=https://wiki.sei.cmu.edu/confluence/display/c/MEM04-C.+Beware+of+zero-length+allocations |website=wiki.sei.cmu.edu}}<!-- Note: the example is bullshit. Freeing NULL is safe because it does nothing. --></ref> यद्यपि [[POSIX]] और ऐकल यूनिक्स विशिष्टता दोनों को 0-आकार के आवंटन के उचित संचालन की आवश्यकता होती है, या तो {{code|NULL}} या कुछ और जो सुरक्षित रूप से मुक्त किया जा सकता है,<ref>{{cite web |title=POSIX.1-2017: malloc |url=https://pubs.opengroup.org/onlinepubs/9699919799/ |website=pubs.opengroup.org |access-date=29 November 2019}}</ref> इन नियमों का पालन करने के लिए सभी प्लेटफार्मों की आवश्यकता नहीं है। इसके कारण होने वाली कई डबल-मुक्त त्रुटियों में, 2019 [[व्हाट्सप्प]] आरसीई विशेष रूप से प्रमुख था।<ref>{{cite web |last1=Awakened |title=How a double-free bug in WhatsApp turns to RCE |date=2 October 2019 |url=https://awakened1712.github.io/hacking/hacking-whatsapp-gif-rce/ |access-date=29 November 2019}}</ref> इन कार्यों को लपेटने की एक शैली उन्हें सुरक्षित बनाने के लिए केवल 0-आकार के आवंटन की जाँच करना और उन्हें आकार 1 में बदलना है। (रिटर्निंग) {{code|NULL}} इसकी अपनी समस्याएँ हैं: यह अन्यथा एक स्मृति से बाहर विफलता का संकेत देता है। {{code|realloc}} के मामले में यह संकेत होगा कि मूल स्मृति को स्थानांतरित नहीं किया गया था और मुक्त नहीं किया गया था, जो फिर से आकार 0 के मामले में नहीं है, जिससे दोगुना-मुक्त हो जाता है।)<ref>{{cite tweet |last1=Felker |first1=Rich |title=Wow. The WhatsApp RCE was the wrong behavior for realloc(p,0) so many implementations insist on. |user=RichFelker |number=1179701167569416192 |access-date=6 August 2022 |date=3 October 2019}}</ref>
== कार्यान्वयन ==
== कार्यान्वयन ==
स्मृति प्रबंधन का कार्यान्वयन काफी हद तक संचालन प्रणाली और आर्किटेक्चर पर निर्भर करता है। कुछ संचालन प्रणाली मॉलोक के लिए आवंटक की आपूर्ति करते हैं, जबकि अन्य डेटा के कुछ क्षेत्रों को नियंत्रित करने के लिए कार्यों की आपूर्ति करते हैं। एक ही गतिशील स्मृति एलोकेटर का उपयोग अक्सर दोनों को लागू करने के लिए किया जाता है <code>malloc</code> और संचालिका <code>new</code> सी ++ में।<ref>{{Cite book |title=Modern C++ Design: Generic Programming and Design Patterns Applied |first=Andrei |last=Alexandrescu |publisher=Addison-Wesley |year=2001 |page=78}}</ref>
स्मृति प्रबंधन का कार्यान्वयन काफी हद तक संचालन प्रणाली और वास्तुकला पर निर्भर करता है। कुछ संचालन प्रणाली मॉलोक के लिए आवंटक की आपूर्ति करते हैं, जबकि अन्य डेटा के कुछ क्षेत्रों को नियंत्रित करने के लिए कार्यों की आपूर्ति करते हैं। एक ही गतिशील स्मृति संभाजक का उपयोग प्रायः <code>malloc</code> और संचालक दोनों को C++ में लागू करने के लिए किया जाता है।<ref>{{Cite book |title=Modern C++ Design: Generic Programming and Design Patterns Applied |first=Andrei |last=Alexandrescu |publisher=Addison-Wesley |year=2001 |page=78}}</ref>
=== हीप-आधारित ===
=== ढेर-आधारित ===
{{see also|sbrk}}
{{see also|sbrk}}
एलोकेटर का कार्यान्वयन सामान्यतः [[ढेर स्मृति]] या [[डेटा खंड]] का उपयोग करके किया जाता है। आवंटक सामान्यतः आवंटन अनुरोधों को पूरा करने के लिए ढेर का विस्तार और अनुबंध करेगा।
संभाजक का कार्यान्वयन सामान्यतः [[ढेर स्मृति]] या [[डेटा खंड]] का उपयोग करके किया जाता है। आवंटक सामान्यतः आवंटन अनुरोधों को पूरा करने के लिए ढेर का विस्तार और अनुबंध करेगा।


ढेर विधि कुछ अंतर्निहित खामियों से ग्रस्त है, जो पूरी तरह से [[विखंडन (कंप्यूटर)]] से उपजी है। स्मृति आबंटन की किसी भी विधि की तरह, हीप खंडित हो जाएगा; यानी, ढेर पर आवंटित स्थान में प्रयुक्त और अप्रयुक्त स्मृति के खंड होंगे। ढेर का विस्तार करने का सहारा लेने से पहले एक अच्छा आवंटक उपयोग करने के लिए पहले से आवंटित स्मृति के अप्रयुक्त क्षेत्र को खोजने का प्रयास करेगा। इस पद्धति के साथ प्रमुख समस्या यह है कि हीप में केवल दो महत्वपूर्ण विशेषताएं हैं: आधार, या वर्चुअल स्मृति स्पेस में हीप की शुरुआत; और लंबाई, या इसका आकार। हीप को अपनी पूरी लंबाई भरने के लिए पर्याप्त प्रणाली स्मृति की आवश्यकता होती है, और इसका आधार कभी नहीं बदल सकता। इस प्रकार, अप्रयुक्त स्मृति का कोई भी बड़ा क्षेत्र बर्बाद हो जाता है। ढेर इस स्थिति में फंस सकता है यदि ढेर के अंत में एक छोटा सा इस्तेमाल किया गया खंड मौजूद है, जो किसी भी पते की जगह को बर्बाद कर सकता है। आलसी स्मृति आवंटन योजनाओं पर, जैसे कि अक्सर लिनक्स संचालन प्रणाली में पाए जाते हैं, एक बड़ा हीप अनिवार्य रूप से समकक्ष प्रणाली स्मृति को आरक्षित नहीं करता है; यह केवल पहली बार लिखने के समय ही ऐसा करेगा (गैर-मैप किए गए स्मृति पेज शून्य पर लौटते हैं)। इसकी ग्रैन्युलैरिटी पृष्ठ आकार पर निर्भर करती है।
ढेर विधि कुछ अंतर्निहित खामियों से ग्रस्त है, जो पूरी तरह से [[विखंडन (कंप्यूटर)]] से उपजी है। स्मृति आबंटन की किसी भी विधि की तरह, ढेर खंडित हो जाएगा; यानी, ढेर पर आवंटित स्थान में प्रयुक्त और अप्रयुक्त स्मृति के खंड होंगे। ढेर का विस्तार करने का सहारा लेने से पहले एक अच्छा आवंटक उपयोग करने के लिए पहले से आवंटित स्मृति के अप्रयुक्त क्षेत्र को खोजने का प्रयास करेगा। इस पद्धति के साथ प्रमुख समस्या यह है कि ढेर में केवल दो महत्वपूर्ण विशेषताएं हैं: आधार, या वर्चुअल स्मृति स्पेस में ढेर की शुरुआत; और लंबाई, या इसका आकार। ढेर को अपनी पूरी लंबाई भरने के लिए पर्याप्त प्रणाली स्मृति की आवश्यकता होती है, और इसका आधार कभी नहीं बदल सकता। इस प्रकार, अप्रयुक्त स्मृति का कोई भी बड़ा क्षेत्र बर्बाद हो जाता है। ढेर इस स्थिति में फंस सकता है यदि ढेर के अंत में एक छोटा सा इस्तेमाल किया गया खंड मौजूद है, जो किसी भी पते की जगह को बर्बाद कर सकता है। आलसी स्मृति आवंटन योजनाओं पर, जैसे कि प्रायः लिनक्स संचालन प्रणाली में पाए जाते हैं, एक बड़ा ढेर अनिवार्य रूप से समकक्ष प्रणाली स्मृति को आरक्षित नहीं करता है; यह केवल पहली बार लिखने के समय ही ऐसा करेगा (गैर-मैप किए गए स्मृति पेज शून्य पर लौटते हैं)। इसकी ग्रैन्युलैरिटी पृष्ठ आकार पर निर्भर करती है।
===dlmalloc और ptmalloc{{anchor|dlmalloc}}===
===dlmalloc और ptmalloc{{anchor|dlmalloc}}===
डग ली ने सार्वजनिक डोमेन dlmalloc ([[Doug Lea]]'s malloc) को एक सामान्य-उद्देश्य आवंटक के रूप में विकसित किया है, जिसकी शुरुआत 1987 में हुई थी। GNU C लाइब्रेरी (glibc) वोल्फ्राम ग्लोगर के ptmalloc (pthreads malloc) से ली गई है, जो थ्रेडिंग से संबंधित dlmalloc का एक कांटा है। सुधार।<ref>{{cite web|url=http://malloc.de/en/|title=Wolfram Gloger's malloc homepage|website=malloc.de|access-date=1 April 2018}}</ref><ref name="phrack-57-8">{{cite journal|last=Kaempf |first=Michel |year=2001 |title=Vudo malloc tricks |journal=[[Phrack]] |issue=57 |page=8 |url=http://phrack.org/issues/57/8.html |access-date=29 April 2009 |url-status=live |archive-url=https://web.archive.org/web/20090122071923/http://www.phrack.org/issues.html?issue=57&id=8&mode=txt |archive-date=22 January 2009 }}</ref><ref>{{cite web |title=Glibc: Malloc Internals |url=https://sourceware.org/glibc/wiki/MallocInternals |website=sourceware.org Trac |access-date=1 December 2019}}</ref> नवंबर 2019 तक, dlmalloc का नवीनतम संस्करण अगस्त 2012 से संस्करण 2.8.6 है।<ref name="dlmalloc">{{cite web |last1=Lee |first1=Doug |title=A Memory Allocator |url=http://gee.cs.oswego.edu/dl/html/malloc.html |access-date=1 December 2019}} [http://gee.cs.oswego.edu/pub/misc/malloc.c HTTP for Source Code]</ref>
डग ली ने सार्वजनिक डोमेन dlmalloc ([[Doug Lea]]'s malloc) को एक सामान्य-उद्देश्य आवंटक के रूप में विकसित किया है, जिसकी शुरुआत 1987 में हुई थी। GNU C लाइब्रेरी (glibc) वोल्फ्राम ग्लोगर के ptmalloc (pthreads malloc) से ली गई है, जो थ्रेडिंग से संबंधित dlmalloc का एक कांटा है। सुधार।<ref>{{cite web|url=http://malloc.de/en/|title=Wolfram Gloger's malloc homepage|website=malloc.de|access-date=1 April 2018}}</ref><ref name="phrack-57-8">{{cite journal|last=Kaempf |first=Michel |year=2001 |title=Vudo malloc tricks |journal=[[Phrack]] |issue=57 |page=8 |url=http://phrack.org/issues/57/8.html |access-date=29 April 2009 |url-status=live |archive-url=https://web.archive.org/web/20090122071923/http://www.phrack.org/issues.html?issue=57&id=8&mode=txt |archive-date=22 January 2009 }}</ref><ref>{{cite web |title=Glibc: Malloc Internals |url=https://sourceware.org/glibc/wiki/MallocInternals |website=sourceware.org Trac |access-date=1 December 2019}}</ref> नवंबर 2019 तक, dlmalloc का नवीनतम संस्करण अगस्त 2012 से संस्करण 2.8.6 है।<ref name="dlmalloc">{{cite web |last1=Lee |first1=Doug |title=A Memory Allocator |url=http://gee.cs.oswego.edu/dl/html/malloc.html |access-date=1 December 2019}} [http://gee.cs.oswego.edu/pub/misc/malloc.c HTTP for Source Code]</ref>
dlmalloc एक सीमा टैग आवंटक है। हीप स्मृति पर स्मृति को चंक्स के रूप में आवंटित किया जाता है, एक 8-बाइट [[डेटा संरचना]] संरेखण डेटा संरचना जिसमें एक हेडर और प्रयोग करने योग्य स्मृति होती है। आवंटित स्मृति में चंक के आकार और उपयोग के झंडे ([[डोप वेक्टर]] के समान) के लिए 8- या 16-बाइट ओवरहेड होता है। अनाबंटित चंक्स उपयोग करने योग्य स्थान क्षेत्र में अन्य मुक्त चंक्स के लिए सूचक्स को भी स्टोर करते हैं, जिससे 32-बिट प्रणाली पर न्यूनतम चंक आकार 16 बाइट्स और 64-बिट प्रणाली पर 24/32 (संरेखण पर निर्भर करता है) बाइट्स बनते हैं।<ref name="phrack-57-8" /><ref name="dlmalloc"/>{{rp|at=2.8.6, Minimum allocated size}}
dlmalloc एक सीमा टैग आवंटक है। ढेर स्मृति पर स्मृति को चंक्स के रूप में आवंटित किया जाता है, एक 8-बाइट [[डेटा संरचना]] संरेखण डेटा संरचना जिसमें एक हेडर और प्रयोग करने योग्य स्मृति होती है। आवंटित स्मृति में चंक के आकार और उपयोग के झंडे ([[डोप वेक्टर]] के समान) के लिए 8- या 16-बाइट ओवरहेड होता है। अनाबंटित चंक्स उपयोग करने योग्य स्थान क्षेत्र में अन्य मुक्त चंक्स के लिए सूचक्स को भी स्टोर करते हैं, जिससे 32-बिट प्रणाली पर न्यूनतम चंक आकार 16 बाइट्स और 64-बिट प्रणाली पर 24/32 (संरेखण पर निर्भर करता है) बाइट्स बनते हैं।<ref name="phrack-57-8" /><ref name="dlmalloc"/>{{rp|at=2.8.6, Minimum allocated size}}
असंबद्ध स्मृति को समान आकार के [[बिन (कम्प्यूटेशनल ज्यामिति)]] में समूहीकृत किया जाता है, जिसे चंक्स की डबल-लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है (चंक के अंदर असंबद्ध स्थान में संग्रहीत सूचक्स के साथ)। डिब्बे आकार के अनुसार तीन वर्गों में क्रमबद्ध होते हैं:<ref name="phrack-57-8" /><ref name="dlmalloc"/>{{rp|at=Overlaid data structures}}
असंबद्ध स्मृति को समान आकार के [[बिन (कम्प्यूटेशनल ज्यामिति)]] में समूहीकृत किया जाता है, जिसे चंक्स की डबल-लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है (चंक के अंदर असंबद्ध स्थान में संग्रहीत सूचक्स के साथ)। डिब्बे आकार के अनुसार तीन वर्गों में क्रमबद्ध होते हैं:<ref name="phrack-57-8" /><ref name="dlmalloc"/>{{rp|at=Overlaid data structures}}
* 256 बाइट्स (स्मॉलबिन अनुरोध) से नीचे के अनुरोधों के लिए, एक साधारण दो पावर बेस्ट फिट एलोकेटर का उपयोग किया जाता है। यदि उस बिन में कोई मुक्त ब्लॉक नहीं है, तो अगले उच्चतम बिन से एक ब्लॉक दो भागों में विभाजित हो जाता है।
* 256 बाइट्स (स्मॉलबिन अनुरोध) से नीचे के अनुरोधों के लिए, एक साधारण दो पावर बेस्ट फिट संभाजक का उपयोग किया जाता है। यदि उस बिन में कोई मुक्त ब्लॉक नहीं है, तो अगले उच्चतम बिन से एक ब्लॉक दो भागों में विभाजित हो जाता है।
* 256 बाइट्स या उससे ऊपर के अनुरोधों के लिए, लेकिन [[mmap]] थ्रेशोल्ड के नीचे, v2.8.0 के बाद से dlmalloc Trie#Bitwise try|in-place बिटवाइज़ ट्राई एल्गोरिथम (ट्रीबिन) का उपयोग करें। यदि अनुरोध को पूरा करने के लिए कोई खाली स्थान नहीं बचा है, तो dlmalloc ढेर के आकार को बढ़ाने की कोशिश करता है, सामान्यतः [[sbrk]] प्रणाली कॉल के माध्यम से। यह सुविधा ptmalloc (v2.7.x से) बनने के बाद पेश की गई थी, और इसके परिणामस्वरूप यह glibc का हिस्सा नहीं है, जो पुराने सबसे फिट आवंटक को विरासत में मिला है।
* 256 बाइट्स या उससे ऊपर के अनुरोधों के लिए, लेकिन [[mmap]] थ्रेशोल्ड के नीचे, v2.8.0 के बाद से dlmalloc Trie#Bitwise try|in-place बिटवाइज़ ट्राई एल्गोरिथम (ट्रीबिन) का उपयोग करें। यदि अनुरोध को पूरा करने के लिए कोई खाली स्थान नहीं बचा है, तो dlmalloc ढेर के आकार को बढ़ाने की कोशिश करता है, सामान्यतः [[sbrk]] प्रणाली कॉल के माध्यम से। यह सुविधा ptmalloc (v2.7.x से) बनने के बाद पेश की गई थी, और इसके परिणामस्वरूप यह glibc का हिस्सा नहीं है, जो पुराने सबसे फिट आवंटक को विरासत में मिला है।
* एमएमएपी थ्रेसहोल्ड (लार्जबिन अनुरोध) से ऊपर के अनुरोधों के लिए, स्मृति हमेशा एमएमएपी प्रणाली कॉल का उपयोग करके आवंटित की जाती है। सीमा सामान्यतः 256 केबी होती है।<ref name="glibc-env">{{cite web |url=https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html |title=Malloc Tunable Parameters |publisher=[[GNU]] |access-date=2 May 2009 }}</ref> एमएमएपी विधि बड़े बफ़र्स के साथ उनकी समाप्ति के बाद अंत में एक छोटे से आवंटन को फंसाने की समस्या को टालती है, लेकिन हमेशा स्मृति के एक पूरे पृष्ठ (कंप्यूटर स्मृति) को आवंटित करती है, जो कई आर्किटेक्चर पर आकार में 4096 बाइट्स है।<ref>{{cite web |last=Sanderson |first=Bruce |url=http://support.microsoft.com/kb/555223 |title=RAM, Virtual Memory, Pagefile and all that stuff |publisher=Microsoft Help and Support |date=12 December 2004 }}</ref>
* एमएमएपी थ्रेसहोल्ड (लार्जबिन अनुरोध) से ऊपर के अनुरोधों के लिए, स्मृति हमेशा एमएमएपी प्रणाली कॉल का उपयोग करके आवंटित की जाती है। सीमा सामान्यतः 256 केबी होती है।<ref name="glibc-env">{{cite web |url=https://www.gnu.org/software/libc/manual/html_node/Malloc-Tunable-Parameters.html |title=Malloc Tunable Parameters |publisher=[[GNU]] |access-date=2 May 2009 }}</ref> एमएमएपी विधि बड़े बफ़र्स के साथ उनकी समाप्ति के बाद अंत में एक छोटे से आवंटन को फंसाने की समस्या को टालती है, लेकिन हमेशा स्मृति के एक पूरे पृष्ठ (कंप्यूटर स्मृति) को आवंटित करती है, जो कई आर्किटेक्चर पर आकार में 4096 बाइट्स है।<ref>{{cite web |last=Sanderson |first=Bruce |url=http://support.microsoft.com/kb/555223 |title=RAM, Virtual Memory, Pagefile and all that stuff |publisher=Microsoft Help and Support |date=12 December 2004 }}</ref>
Line 125: Line 131:
=== होर्ड मॉलोक ===
=== होर्ड मॉलोक ===
{{main|Hoard memory allocator}}
{{main|Hoard memory allocator}}
होर्ड एक एलोकेटर है जिसका लक्ष्य स्केलेबल स्मृति आवंटन प्रदर्शन है। OpenBSD के संभाजक की तरह, होर्ड उपयोग करता है <code>mmap</code> विशेष रूप से, लेकिन सुपरब्लॉक कहे जाने वाले 64 किलोबाइट के टुकड़ों में स्मृति का प्रबंधन करता है। होर्ड के हीप को तार्किक रूप से एक ग्लोबल हीप और कई प्रति-प्रोसेसर हीप में विभाजित किया गया है। इसके अलावा, एक थ्रेड-लोकल कैश है जो सीमित संख्या में सुपरब्लॉक रख सकता है। स्थानीय प्रति-थ्रेड या प्रति-प्रोसेसर हीप पर केवल सुपरब्लॉक से आवंटित करके, और ज्यादातर खाली सुपरब्लॉक को ग्लोबल हीप में ले जाकर अन्य प्रोसेसर द्वारा पुन: उपयोग किया जा सकता है, थ्रेड्स की संख्या के साथ रैखिक मापनीयता प्राप्त करते समय होर्ड विखंडन को कम रखता है .<ref>{{Cite conference | doi = 10.1145/378993.379232| title = Hoard: A Scalable Memory Allocator for Multithreaded Applications| work = Proceedings of the ninth international conference on Architectural support for programming languages and operating systems| conference = [[International Conference on Architectural Support for Programming Languages and Operating Systems|ASPLOS]]-IX| pages = 117–128| date=November 2000 | last1 = Berger | first1 = E. D. | last2 = McKinley | first2 = K. S. |author2-link = Kathryn S. McKinley| last3 = Blumofe | first3 = R. D. | last4 = Wilson | first4 = P. R. | isbn = 1-58113-317-0| url = http://www.cs.umass.edu/~emery/pubs/berger-asplos2000.pdf| citeseerx = 10.1.1.1.4174}}</ref>
होर्ड एक संभाजक है जिसका लक्ष्य स्केलेबल स्मृति आवंटन प्रदर्शन है। OpenBSD के संभाजक की तरह, होर्ड उपयोग करता है <code>mmap</code> विशेष रूप से, लेकिन सुपरब्लॉक कहे जाने वाले 64 किलोबाइट के टुकड़ों में स्मृति का प्रबंधन करता है। होर्ड के ढेर को तार्किक रूप से एक ग्लोबल ढेर और कई प्रति-प्रोसेसर ढेर में विभाजित किया गया है। इसके अलावा, एक थ्रेड-लोकल कैश है जो सीमित संख्या में सुपरब्लॉक रख सकता है। स्थानीय प्रति-थ्रेड या प्रति-प्रोसेसर ढेर पर केवल सुपरब्लॉक से आवंटित करके, और ज्यादातर खाली सुपरब्लॉक को ग्लोबल ढेर में ले जाकर अन्य प्रोसेसर द्वारा पुन: उपयोग किया जा सकता है, थ्रेड्स की संख्या के साथ रैखिक मापनीयता प्राप्त करते समय होर्ड विखंडन को कम रखता है .<ref>{{Cite conference | doi = 10.1145/378993.379232| title = Hoard: A Scalable Memory Allocator for Multithreaded Applications| work = Proceedings of the ninth international conference on Architectural support for programming languages and operating systems| conference = [[International Conference on Architectural Support for Programming Languages and Operating Systems|ASPLOS]]-IX| pages = 117–128| date=November 2000 | last1 = Berger | first1 = E. D. | last2 = McKinley | first2 = K. S. |author2-link = Kathryn S. McKinley| last3 = Blumofe | first3 = R. D. | last4 = Wilson | first4 = P. R. | isbn = 1-58113-317-0| url = http://www.cs.umass.edu/~emery/pubs/berger-asplos2000.pdf| citeseerx = 10.1.1.1.4174}}</ref>
=== मिमललोक ===
=== मिमललोक ===
{{main|mimalloc}}
{{main|mimalloc}}
प्रदर्शन पर ध्यान देने के साथ [[माइक्रोसॉफ्ट रिसर्च]] से एक [[खुला स्त्रोत]] | ओपन-सोर्स कॉम्पैक्ट सामान्य-उद्देश्य [[मेमोरी एलोकेटर|स्मृति एलोकेटर]]।<ref>[https://slashdot.org/firehose.pl?op=view&id=110928452 Microsoft releases optimized malloc() as open source - Slashdot]</ref> लाइब्रेरी कोड की लगभग 11,000 पंक्तियाँ हैं।
प्रदर्शन पर ध्यान देने के साथ [[माइक्रोसॉफ्ट रिसर्च]] से एक [[खुला स्त्रोत]] | ओपन-सोर्स कॉम्पैक्ट सामान्य-उद्देश्य [[मेमोरी एलोकेटर|स्मृति संभाजक]]।<ref>[https://slashdot.org/firehose.pl?op=view&id=110928452 Microsoft releases optimized malloc() as open source - Slashdot]</ref> लाइब्रेरी कोड की लगभग 11,000 पंक्तियाँ हैं।
=== थ्रेड-कैशिंग मॉलोक (tcmalloc) ===
=== थ्रेड-कैशिंग मॉलोक (tcmalloc) ===
छोटे आवंटन के लिए प्रत्येक थ्रेड में [[थ्रेड-लोकल स्टोरेज]] होता है। बड़े आवंटन के लिए mmap या sbrk का उपयोग किया जा सकता है। [https://code.google.com/p/gperftools/ TCMalloc], Google द्वारा विकसित एक malloc,<ref>[//code.google.com/p/gperftools/ TCMalloc homepage]</ref> मृत धागे के स्थानीय भंडारण के लिए कचरा संग्रह है। TCMalloc को बहुप्रचारित क्रमादेशों के लिए glibc के ptmalloc से दुगने से भी अधिक तेज़ माना जाता है।<ref>Ghemawat, Sanjay; Menage, Paul; [http://goog-perftools.sourceforge.net/doc/tcmalloc.html ''TCMalloc : Thread-Caching Malloc'']</ref><ref>{{cite web |first=Mark |last=Callaghan |url=http://mysqlha.blogspot.com/2009/01/double-sysbench-throughput-with_18.html |title=High Availability MySQL: Double sysbench throughput with TCMalloc |work=Mysqlha.blogspot.com |date=18 January 2009 |access-date=18 September 2011 }}</ref>
छोटे आवंटन के लिए प्रत्येक थ्रेड में [[थ्रेड-लोकल स्टोरेज]] होता है। बड़े आवंटन के लिए mmap या sbrk का उपयोग किया जा सकता है। [https://code.google.com/p/gperftools/ TCMalloc], Google द्वारा विकसित एक malloc,<ref>[//code.google.com/p/gperftools/ TCMalloc homepage]</ref> मृत धागे के स्थानीय भंडारण के लिए कचरा संग्रह है। TCMalloc को बहुप्रचारित क्रमादेशों के लिए glibc के ptmalloc से दुगने से भी अधिक तेज़ माना जाता है।<ref>Ghemawat, Sanjay; Menage, Paul; [http://goog-perftools.sourceforge.net/doc/tcmalloc.html ''TCMalloc : Thread-Caching Malloc'']</ref><ref>{{cite web |first=Mark |last=Callaghan |url=http://mysqlha.blogspot.com/2009/01/double-sysbench-throughput-with_18.html |title=High Availability MySQL: Double sysbench throughput with TCMalloc |work=Mysqlha.blogspot.com |date=18 January 2009 |access-date=18 September 2011 }}</ref>
=== इन-कर्नेल ===
=== इन-कर्नेल ===
संचालन प्रणाली कर्नेल (कंप्यूटर साइंस) को एप्लिकेशन क्रमादेश की तरह ही स्मृति आवंटित करने की आवश्यकता होती है। का कार्यान्वयन <code>malloc</code> तथापि, कर्नेल के भीतर अक्सर सी लाइब्रेरीों द्वारा उपयोग किए जाने वाले कार्यान्वयन से काफी भिन्न होता है। उदाहरण के लिए, स्मृति बफ़र्स को [[प्रत्यक्ष मेमोरी एक्सेस|प्रत्यक्ष स्मृति एक्सेस]] द्वारा लगाए गए विशेष प्रतिबंधों के अनुरूप होने की आवश्यकता हो सकती है, या स्मृति आवंटन फलन को इंटरप्ट संदर्भ से कॉल किया जा सकता है।<ref>{{cite web |url=http://people.netfilter.org/rusty/unreliable-guides/kernel-hacking/routines-kmalloc.html |title=kmalloc()/kfree() include/linux/slab.h |work=People.netfilter.org |access-date=18 September 2011 }}</ref> यह एक की आवश्यकता है <code>malloc</code> कार्यान्वयन संचालन प्रणाली कर्नेल के [[आभासी मेमोरी|आभासी स्मृति]] सबप्रणाली के साथ कसकर एकीकृत है।
संचालन प्रणाली कर्नेल (कंप्यूटर साइंस) को एप्लिकेशन क्रमादेश की तरह ही स्मृति आवंटित करने की आवश्यकता होती है। का कार्यान्वयन <code>malloc</code> तथापि, कर्नेल के भीतर प्रायः सी लाइब्रेरीों द्वारा उपयोग किए जाने वाले कार्यान्वयन से काफी भिन्न होता है। उदाहरण के लिए, स्मृति बफ़र्स को [[प्रत्यक्ष मेमोरी एक्सेस|प्रत्यक्ष स्मृति एक्सेस]] द्वारा लगाए गए विशेष प्रतिबंधों के अनुरूप होने की आवश्यकता हो सकती है, या स्मृति आवंटन फलन को इंटरप्ट संदर्भ से कॉल किया जा सकता है।<ref>{{cite web |url=http://people.netfilter.org/rusty/unreliable-guides/kernel-hacking/routines-kmalloc.html |title=kmalloc()/kfree() include/linux/slab.h |work=People.netfilter.org |access-date=18 September 2011 }}</ref> यह एक की आवश्यकता है <code>malloc</code> कार्यान्वयन संचालन प्रणाली कर्नेल के [[आभासी मेमोरी|आभासी स्मृति]] सबप्रणाली के साथ कसकर एकीकृत है।


== मॉलोक ओवरराइडिंग ==
== मॉलोक ओवरराइडिंग ==
क्योंकि  <code>malloc</code> और उसके रिश्तेदार किसी क्रमादेश के प्रदर्शन पर गहरा प्रभाव डाल सकते हैं,<!--TODO: cite Bentley's Programming Pearls--> एप्लिकेशन के आवंटन पैटर्न के लिए अनुकूलित किए गए कस्टम कार्यान्वयन द्वारा किसी विशिष्ट एप्लिकेशन के कार्यों को ओवरराइड करना असामान्य नहीं है। सी मानक ऐसा करने का कोई तरीका प्रदान नहीं करता है, लेकिन संचालन प्रणाली ने गतिशील लिंकिंग का फायदा उठाकर ऐसा करने के कई तरीके खोजे हैं। प्रतीकों को ओवरराइड करने के लिए एक तरीका केवल एक अलग लाइब्रेरी में लिंक करना है। एक अन्य, UNIX System V#SVR3|Unix System V.3 द्वारा नियोजित, बनाना है <code>malloc</code> और <code>free</code> फलन सूचक्स जो एक एप्लिकेशन कस्टम प्रकार्य पर रीसेट कर सकता है।<ref name="Levine_1999_CH9"/>
क्योंकि  <code>malloc</code> और उसके रिश्तेदार किसी क्रमादेश के प्रदर्शन पर गहरा प्रभाव डाल सकते हैं,<!--TODO: cite Bentley's Programming Pearls--> एप्लिकेशन के आवंटन प्रतिरूप के लिए अनुकूलित किए गए कस्टम कार्यान्वयन द्वारा किसी विशिष्ट एप्लिकेशन के कार्यों को ओवरराइड करना असामान्य नहीं है। सी मानक ऐसा करने का कोई तरीका प्रदान नहीं करता है, लेकिन संचालन प्रणाली ने गतिशील लिंकिंग का फायदा उठाकर ऐसा करने के कई तरीके खोजे हैं। प्रतीकों को ओवरराइड करने के लिए एक तरीका केवल एक अलग लाइब्रेरी में लिंक करना है। एक अन्य, UNIX System V#SVR3|Unix System V.3 द्वारा नियोजित, बनाना है <code>malloc</code> और <code>free</code> फलन सूचक्स जो एक एप्लिकेशन कस्टम प्रकार्य पर रीसेट कर सकता है।<ref name="Levine_1999_CH9"/>


POSIX-जैसी प्रणालियों पर सबसे आम रूप पर्यावरण चर LD_PRELOAD को आवंटक के पथ के साथ सेट करना है, ताकि गतिशील लिंकर libc कार्यान्वयन के बजाय malloc/calloc/free के उस संस्करण का उपयोग करे।
POSIX-जैसी प्रणालियों पर सबसे आम रूप पर्यावरण चर LD_PRELOAD को आवंटक के पथ के साथ सेट करना है, ताकि गतिशील लिंकर libc कार्यान्वयन के बजाय malloc/calloc/free के उस संस्करण का उपयोग करे।

Revision as of 15:49, 5 March 2023

सी गतिशील स्मृति आवंटन, सी क्रमादेशन भाषा में सी क्रमादेशन भाषा में प्रकार्य के समूह के माध्यम से मॉलोक, रियललोक, कॉलोक, एलायंस_आलोक और निःशुल्कके माध्यम से गतिशील स्मृति आवंटन के लिए मैनुअल स्मृति प्रबंधन करने को संदर्भित करता है।[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-बिट है), यह त्रुटि वास्तव में अपरिभाषित व्यवहार का परिणाम हो सकती है, क्योंकि निहित रूप से घोषित malloc32- रिटर्न देता है। बिट मान जबकि वास्तव में परिभाषित फलन 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]

ढेर-आधारित

संभाजक का कार्यान्वयन सामान्यतः ढेर स्मृति या डेटा खंड का उपयोग करके किया जाता है। आवंटक सामान्यतः आवंटन अनुरोधों को पूरा करने के लिए ढेर का विस्तार और अनुबंध करेगा।

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

dlmalloc और ptmalloc

डग ली ने सार्वजनिक डोमेन dlmalloc (Doug Lea's malloc) को एक सामान्य-उद्देश्य आवंटक के रूप में विकसित किया है, जिसकी शुरुआत 1987 में हुई थी। GNU C लाइब्रेरी (glibc) वोल्फ्राम ग्लोगर के ptmalloc (pthreads malloc) से ली गई है, जो थ्रेडिंग से संबंधित dlmalloc का एक कांटा है। सुधार।[20][21][22] नवंबर 2019 तक, dlmalloc का नवीनतम संस्करण अगस्त 2012 से संस्करण 2.8.6 है।[23] dlmalloc एक सीमा टैग आवंटक है। ढेर स्मृति पर स्मृति को चंक्स के रूप में आवंटित किया जाता है, एक 8-बाइट डेटा संरचना संरेखण डेटा संरचना जिसमें एक हेडर और प्रयोग करने योग्य स्मृति होती है। आवंटित स्मृति में चंक के आकार और उपयोग के झंडे (डोप वेक्टर के समान) के लिए 8- या 16-बाइट ओवरहेड होता है। अनाबंटित चंक्स उपयोग करने योग्य स्थान क्षेत्र में अन्य मुक्त चंक्स के लिए सूचक्स को भी स्टोर करते हैं, जिससे 32-बिट प्रणाली पर न्यूनतम चंक आकार 16 बाइट्स और 64-बिट प्रणाली पर 24/32 (संरेखण पर निर्भर करता है) बाइट्स बनते हैं।[21][23]: 2.8.6, Minimum allocated size  असंबद्ध स्मृति को समान आकार के बिन (कम्प्यूटेशनल ज्यामिति) में समूहीकृत किया जाता है, जिसे चंक्स की डबल-लिंक्ड सूची का उपयोग करके कार्यान्वित किया जाता है (चंक के अंदर असंबद्ध स्थान में संग्रहीत सूचक्स के साथ)। डिब्बे आकार के अनुसार तीन वर्गों में क्रमबद्ध होते हैं:[21][23]: Overlaid data structures 

  • 256 बाइट्स (स्मॉलबिन अनुरोध) से नीचे के अनुरोधों के लिए, एक साधारण दो पावर बेस्ट फिट संभाजक का उपयोग किया जाता है। यदि उस बिन में कोई मुक्त ब्लॉक नहीं है, तो अगले उच्चतम बिन से एक ब्लॉक दो भागों में विभाजित हो जाता है।
  • 256 बाइट्स या उससे ऊपर के अनुरोधों के लिए, लेकिन mmap थ्रेशोल्ड के नीचे, v2.8.0 के बाद से dlmalloc Trie#Bitwise try|in-place बिटवाइज़ ट्राई एल्गोरिथम (ट्रीबिन) का उपयोग करें। यदि अनुरोध को पूरा करने के लिए कोई खाली स्थान नहीं बचा है, तो dlmalloc ढेर के आकार को बढ़ाने की कोशिश करता है, सामान्यतः sbrk प्रणाली कॉल के माध्यम से। यह सुविधा ptmalloc (v2.7.x से) बनने के बाद पेश की गई थी, और इसके परिणामस्वरूप यह glibc का हिस्सा नहीं है, जो पुराने सबसे फिट आवंटक को विरासत में मिला है।
  • एमएमएपी थ्रेसहोल्ड (लार्जबिन अनुरोध) से ऊपर के अनुरोधों के लिए, स्मृति हमेशा एमएमएपी प्रणाली कॉल का उपयोग करके आवंटित की जाती है। सीमा सामान्यतः 256 केबी होती है।[24] एमएमएपी विधि बड़े बफ़र्स के साथ उनकी समाप्ति के बाद अंत में एक छोटे से आवंटन को फंसाने की समस्या को टालती है, लेकिन हमेशा स्मृति के एक पूरे पृष्ठ (कंप्यूटर स्मृति) को आवंटित करती है, जो कई आर्किटेक्चर पर आकार में 4096 बाइट्स है।[25]

गेम डेवलपर एड्रियन स्टोन का तर्क है कि dlmalloc, एक सीमा-टैग आवंटक के रूप में, कंसोल प्रणाली के लिए अमित्र है जिसमें वर्चुअल स्मृति है लेकिन मांग पेजिंग नहीं है। ऐसा इसलिए है क्योंकि इसके पूल-सिकुड़ते और बढ़ते कॉलबैक (सिसालोक/सिस्ट्रिम) का उपयोग वर्चुअल स्मृति के अलग-अलग पेजों को आवंटित करने और कमिट करने के लिए नहीं किया जा सकता है। डिमांड पेजिंग के अभाव में विखंडन एक बड़ी चिंता बन जाता है।[26]

FreeBSD's और NetBSD's jemalloc

FreeBSD 7.0 और NetBSD 5.0 ​​के बाद से, पुराना malloc कार्यान्वयन (Poul-Henning Kamp द्वारा phkmalloc) को जेसन इवांस द्वारा लिखित jemalloc द्वारा प्रतिस्थापित किया गया था। इसका मुख्य कारण मल्टीथ्रेडिंग के मामले में phkmalloc की मापनीयता की कमी थी। लॉक विवाद से बचने के लिए, जेमलोक प्रत्येक केंद्रीय प्रसंस्करण इकाई के लिए अलग-अलग एरेनास का उपयोग करता है। मल्टीथ्रेडिंग एप्लिकेशन में प्रति सेकंड आवंटन की संख्या को मापने वाले प्रयोगों से पता चला है कि यह इसे थ्रेड्स की संख्या के साथ रैखिक रूप से स्केल करता है, जबकि phkmalloc और dlmalloc दोनों के लिए प्रदर्शन थ्रेड्स की संख्या के व्युत्क्रमानुपाती था।[27]

ओपनबीएसडी का मॉलोक

OpenBSD का कार्यान्वयन malloc समारोह एमएमएपी का उपयोग करता है। एक पृष्ठ से बड़े आकार के अनुरोधों के लिए, संपूर्ण आवंटन का उपयोग करके पुनर्प्राप्त किया जाता है mmap; द्वारा अनुरक्षित स्मृति पूल से छोटे आकार निर्दिष्ट किए जाते हैं malloc कई बकेट पेजों के भीतर, साथ ही आवंटित भी mmap.[28][better source needed] एक कॉल पर free, स्मृति को रिलीज़ किया जाता है और प्रोसेस पता स्थान का उपयोग करके अनमैप किया जाता है munmap. इस प्रणाली को ओपनबीएसडी के हिस्से के रूप में कार्यान्वित एड्रेस स्पेस लेआउट रैंडमाइजेशन और गैप पेज सुविधाओं का लाभ उठाकर सुरक्षा में सुधार करने के लिए डिज़ाइन किया गया है। mmap प्रणाली कॉल, और उपयोग-बाद-मुक्त बग का पता लगाने के लिए- चूंकि एक बड़ी स्मृति आवंटन मुक्त होने के बाद पूरी तरह से मैप नहीं किया गया है, आगे के उपयोग से विभाजन की गलती और क्रमादेश की समाप्ति का कारण बनता है।

होर्ड मॉलोक

होर्ड एक संभाजक है जिसका लक्ष्य स्केलेबल स्मृति आवंटन प्रदर्शन है। OpenBSD के संभाजक की तरह, होर्ड उपयोग करता है mmap विशेष रूप से, लेकिन सुपरब्लॉक कहे जाने वाले 64 किलोबाइट के टुकड़ों में स्मृति का प्रबंधन करता है। होर्ड के ढेर को तार्किक रूप से एक ग्लोबल ढेर और कई प्रति-प्रोसेसर ढेर में विभाजित किया गया है। इसके अलावा, एक थ्रेड-लोकल कैश है जो सीमित संख्या में सुपरब्लॉक रख सकता है। स्थानीय प्रति-थ्रेड या प्रति-प्रोसेसर ढेर पर केवल सुपरब्लॉक से आवंटित करके, और ज्यादातर खाली सुपरब्लॉक को ग्लोबल ढेर में ले जाकर अन्य प्रोसेसर द्वारा पुन: उपयोग किया जा सकता है, थ्रेड्स की संख्या के साथ रैखिक मापनीयता प्राप्त करते समय होर्ड विखंडन को कम रखता है .[29]

मिमललोक

प्रदर्शन पर ध्यान देने के साथ माइक्रोसॉफ्ट रिसर्च से एक खुला स्त्रोत | ओपन-सोर्स कॉम्पैक्ट सामान्य-उद्देश्य स्मृति संभाजक[30] लाइब्रेरी कोड की लगभग 11,000 पंक्तियाँ हैं।

थ्रेड-कैशिंग मॉलोक (tcmalloc)

छोटे आवंटन के लिए प्रत्येक थ्रेड में थ्रेड-लोकल स्टोरेज होता है। बड़े आवंटन के लिए mmap या sbrk का उपयोग किया जा सकता है। TCMalloc, Google द्वारा विकसित एक malloc,[31] मृत धागे के स्थानीय भंडारण के लिए कचरा संग्रह है। TCMalloc को बहुप्रचारित क्रमादेशों के लिए glibc के ptmalloc से दुगने से भी अधिक तेज़ माना जाता है।[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. 1.0 1.1 7.20.3 Memory management functions (PDF). p. 313. {{cite book}}: |work= ignored (help)
  2. Summit, Steve. "Chapter 11: Memory Allocation". C Programming Notes. Retrieved 2020-07-11.
  3. "aligned_alloc(3) - Linux man page".
  4. Stroustrup, Bjarne (2008). Programming: Principles and Practice Using C++. Addison Wesley. p. 1009. ISBN 978-0-321-54372-1.
  5. "gcc manual". gnu.org. Retrieved 2008-12-14.
  6. Brian W. Kernighan, Dennis M. Ritchie, The C Programming Language, Prentice-Hall, 1978; Section 7.9 (page 156) describes calloc and cfree, and Section 8.7 (page 173) describes an implementation for alloc and free.
  7. alloc(3) – Version 6 Unix Programmer's Manual
  8. malloc(3) – Version 7 Unix Programmer's Manual
  9. Anonymous, Unix Programmer's Manual, Vol. 1, Holt Rinehart and Winston, 1983 (copyright held by Bell Telephone Laboratories, 1983, 1979); The man page for malloc etc. is given on page 275.
  10. alloca(3) – FreeBSD Library Functions Manual
  11. calloc(3) – Linux Programmer's Manual – Library Functions
  12. 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.
  13. "comp.lang.c FAQ list · Question 7.7b". C-FAQ. Retrieved 2007-03-09.
  14. Reek, Kenneth (1997-08-04). Pointers on C (in English) (1 ed.). Pearson. ISBN 9780673999863.
  15. "MEM04-C. Beware of zero-length allocations - SEI CERT C Coding Standard - Confluence". wiki.sei.cmu.edu.
  16. "POSIX.1-2017: malloc". pubs.opengroup.org. Retrieved 2019-11-29.
  17. Awakened (2019-10-02). "How a double-free bug in WhatsApp turns to RCE". Retrieved 2019-11-29.
  18. 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.
  19. Alexandrescu, Andrei (2001). Modern C++ Design: Generic Programming and Design Patterns Applied. Addison-Wesley. p. 78.
  20. "Wolfram Gloger's malloc homepage". malloc.de. Retrieved 2018-04-01.
  21. 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.
  22. "Glibc: Malloc Internals". sourceware.org Trac. Retrieved 2019-12-01.
  23. 23.0 23.1 23.2 Lee, Doug. "A Memory Allocator". Retrieved 2019-12-01. HTTP for Source Code
  24. "Malloc Tunable Parameters". GNU. Retrieved 2009-05-02.
  25. Sanderson, Bruce (2004-12-12). "RAM, Virtual Memory, Pagefile and all that stuff". Microsoft Help and Support.
  26. Stone, Adrian. "The Hole That dlmalloc Can't Fill". Game Angst. Retrieved 2019-12-01.
  27. Evans, Jason (2006-04-16). "A Scalable Concurrent malloc(3) Implementation for FreeBSD" (PDF). Retrieved 2012-03-18.
  28. "libc/stdlib/malloc.c". BSD Cross Reference, OpenBSD src/lib/.
  29. 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.
  30. Microsoft releases optimized malloc() as open source - Slashdot
  31. TCMalloc homepage
  32. Ghemawat, Sanjay; Menage, Paul; TCMalloc : Thread-Caching Malloc
  33. Callaghan, Mark (2009-01-18). "High Availability MySQL: Double sysbench throughput with TCMalloc". Mysqlha.blogspot.com. Retrieved 2011-09-18.
  34. "kmalloc()/kfree() include/linux/slab.h". People.netfilter.org. Retrieved 2011-09-18.
  35. 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]
  36. "malloc: make malloc fail with requests larger than PTRDIFF_MAX". Sourceware Bugzilla. 2019-04-18. Retrieved 2020-07-30.
  37. "Why is the use of alloca() not considered good practice?". stackoverflow.com. Retrieved 2016-01-05.
  38. 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.
  39. "alloca(3) - Linux manual page". man7.org. Retrieved 2016-01-05.
  40. posix_memalign – System Interfaces Reference, The Single UNIX Specification, Version 4 from The Open Group


बाहरी संबंध