अन्य उत्तरों के अलावा, मैं यह जोड़ना चाहूंगा कि जब स्टैक और हीप स्पेस के बीच रैम को ऊपर किया जाता है, तो आपको स्थैतिक गैर-स्थिर डेटा (जैसे फ़ाइल ग्लोबल्स, फ़ंक्शन स्टेटिक्स और प्रोग्राम-वाइड) के लिए स्थान पर विचार करना होगा C परिप्रेक्ष्य से ग्लोबल्स, और शायद C ++ के लिए अन्य)।
स्टैक / हीप आवंटन कैसे काम करता है
यह ध्यान देने योग्य है कि स्टार्टअप असेंबली फ़ाइल क्षेत्र को परिभाषित करने का एक तरीका है; टूलचेन (आपके बिल्ड वातावरण और रन-टाइम वातावरण दोनों) ज्यादातर उन प्रतीकों के बारे में परवाह करते हैं जो स्टैकस्पेस की शुरुआत को परिभाषित करते हैं (वेक्टर टेबल में प्रारंभिक स्टैक पॉइंटर को स्टोर करने के लिए उपयोग किया जाता है) और हीप स्पेस की शुरुआत और अंत (डायनामिक द्वारा उपयोग किया जाता है) मेमोरी एलोकेटर, आम तौर पर आपके libc द्वारा प्रदान किया जाता है)
ओपी के उदाहरण में, केवल 2 प्रतीकों को परिभाषित किया गया है, 1kiB पर ढेर का आकार और 0B पर ढेर का आकार। ये मान वास्तव में स्टैक और हीप स्पेस बनाने के लिए कहीं और उपयोग किए जाते हैं
@Gilles उदाहरण में, आकार को परिभाषित किया जाता है और असेंबली फ़ाइल में एक स्टैक स्पेस सेट करने के लिए उपयोग किया जाता है, जहाँ भी स्टैक स्पेस शुरू होता है और आकार को स्थायी करता है, जिसे प्रतीक Stack_Mem द्वारा पहचाना जाता है और अंत में एक लेबल __initial_sp सेट करता है। इसी तरह ढेर के लिए, जहां स्थान प्रतीक Heap_Mem (आकार में 0.5kiB) है, लेकिन शुरुआत और अंत में लेबल के साथ (__heap_base और __heap_limit)।
इन्हें लिंकर द्वारा संसाधित किया जाता है, जो स्टैक स्पेस और हीप स्पेस के भीतर कुछ भी आवंटित नहीं करेगा क्योंकि यह मेमोरी कब्जे में है (Stack_Mem और Heap_Mem प्रतीकों द्वारा), लेकिन यह उन यादों और सभी ग्लोबल्स को जगह दे सकता है जिनकी उन्हें आवश्यकता है। लेबल दिए गए पते पर बिना किसी लंबाई के प्रतीक हैं। लिंक समय पर वेक्टर तालिका के लिए सीधे __initial_sp का उपयोग किया जाता है, और आपके रनटाइम कोड द्वारा __heap_base और __heap_limit। प्रतीकों के वास्तविक पते लिंकर द्वारा असाइन किए जाते हैं, जहां यह उन्हें रखा गया है।
जैसा कि मैंने ऊपर कहा था, इन प्रतीकों को वास्तव में एक स्टार्टअप से नहीं आना चाहिए। फाइल। वे आपके लिंकर कॉन्फ़िगरेशन (केइल में स्कैटर लोड फ़ाइल, जीएनयू में लिंकरस्क्रिप्ट) से आ सकते हैं, और उन पर आप प्लेसमेंट पर बेहतर नियंत्रण रख सकते हैं। उदाहरण के लिए, आप स्टैक को रैम की शुरुआत या अंत में होने के लिए मजबूर कर सकते हैं, या अपने ग्लोबल्स को ढेर से दूर रख सकते हैं, या जो भी आप चाहते हैं। आप यह भी निर्दिष्ट कर सकते हैं कि HEAP या STACK बस कब्जा कर लेती है जो भी ग्लोबल्स रखे जाने के बाद RAM बची रहती है। ध्यान दें कि आपको सावधान रहना होगा कि अधिक स्थिर चर जोड़ने से आपकी अन्य मेमोरी कम हो जाएगी।
हालांकि, प्रत्येक टूलचैन अलग है, और कॉन्फ़िगरेशन फ़ाइल कैसे लिखनी है और आपके डायनामिक मेमोरी एलोकेटर का उपयोग करने वाले प्रतीकों को आपके विशेष वातावरण के प्रलेखन से आना होगा।
ढेर का आकार
स्टैक आकार का निर्धारण करने के तरीके के रूप में, कई टूलचिन्स आपको अपने प्रोग्राम के फ़ंक्शन कॉल ट्री का विश्लेषण करके अधिकतम स्टैक डेप्थ दे सकते हैं, यदि आप पुनरावृत्ति या फ़ंक्शन पॉइंटर्स का उपयोग नहीं करते हैं। यदि आप उन का उपयोग करते हैं, तो एक स्टैक के आकार का अनुमान लगाते हैं और इसे कार्डिनल मानों के साथ पहले से भरते हैं (शायद मुख्य से पहले प्रवेश समारोह के माध्यम से) और फिर अपने कार्यक्रम के बाद थोड़ी देर के लिए जाँच करें कि अधिकतम गहराई कहां थी (जो कि कार्डिनल मान है समाप्त)। यदि आपने अपने प्रोग्राम को पूरी तरह से इसकी सीमा तक प्रयोग कर लिया है, तो आपको काफी सटीक रूप से पता चल जाएगा कि क्या आप स्टैक को सिकोड़ सकते हैं या, यदि आपका प्रोग्राम क्रैश हो जाता है या कोई कार्डिनल वैल्यू नहीं बची है, तो आपको स्टैक को बढ़ाने और फिर से प्रयास करने की आवश्यकता है।
हीप साइज़िंग
हीप आकार का निर्धारण थोड़ा अधिक अनुप्रयोग पर निर्भर है। यदि आप केवल स्टार्टअप के दौरान गतिशील आवंटन करते हैं, तो आप अपने स्टार्टअप कोड में आवश्यक स्थान जोड़ सकते हैं (साथ ही स्मृति प्रबंधन के लिए कुछ ओवरहेड)। यदि आपके पास अपने मेमोरी मैनेजर के स्रोत तक पहुंच है, तो आप यह जान सकते हैं कि ओवरहेड क्या है, और संभवतः आपको उपयोग की जानकारी देने के लिए मेमोरी चलने के लिए कोड भी लिखें। उन अनुप्रयोगों के लिए जिन्हें डायनेमिक रनटाइम मेमोरी की आवश्यकता होती है (उदाहरण के लिए इनबाउंड ईथरनेट फ्रेम के लिए बफ़र्स आवंटित करना) सबसे अच्छा मैं सुझाव दे सकता हूं कि अपने स्टैकाइज को सावधानीपूर्वक करें और ढेर और स्टैटिक्स के बाद जो कुछ बचा है उसे हीप दें।
अंतिम नोट (RTOS)
ओपी के प्रश्न को नंगे-धातु के लिए टैग किया गया था, लेकिन मैं आरटीओएस के लिए एक नोट जोड़ना चाहता हूं। अक्सर (हमेशा?) प्रत्येक कार्य / प्रक्रिया / धागा (मैं सिर्फ यहाँ कार्य को सरलता के लिए लिखूंगा) जब कार्य बनाया जाता है, तो एक स्टैक का आकार दिया जाएगा (टास्क स्टैक्स के अलावा, संभवतः एक छोटा ओएस होगा स्टैक (इंटरप्ट के लिए उपयोग किया जाता है और इस तरह)
कार्य लेखा संरचना और ढेर कहीं से आवंटित किया जाना है, और यह अक्सर आपके आवेदन के समग्र ढेर स्थान से होगा। इन उदाहरणों में, आपका प्रारंभिक स्टैक आकार अक्सर मायने नहीं रखेगा, क्योंकि OS केवल इनिशियलाइज़ेशन के दौरान इसका उपयोग करेगा। मैंने देखा है, उदाहरण के लिए, लिंक करने के दौरान सभी शेष स्थान को HEAP को आवंटित किया जाना और ढेर के अंत में प्रारंभिक स्टैक पॉइंटर को रखना, ढेर में जाने के लिए, यह जानकर कि ओएस ढेर की शुरुआत से आवंटित करेगा। आरंभिक_एसपी स्टैक को छोड़ने से ठीक पहले ओएस स्टैक आवंटित करेगा। फिर अंतरिक्ष के सभी का उपयोग कार्य स्टैक और अन्य गतिशील रूप से आवंटित स्मृति को आवंटित करने के लिए किया जाता है।