क्या एक एम्बेडेड सिस्टम में एकल सरणी के लिए ढेर की एक बड़ी राशि आवंटित करने में एक खामी है?


12

मुझे आमतौर पर यह तय करने में कोई समस्या नहीं है कि कुछ डेटा वैश्विक होना चाहिए, स्थिर या स्टैक पर (यहां कोई गतिशील आवंटन नहीं है, इसलिए ढेर का कोई उपयोग नहीं)। मैंने कुछ क्यू / ए भी पढ़ा है जैसे कि यह एक है लेकिन मेरा प्रश्न अधिक विशिष्ट है क्योंकि इसमें बड़ी मात्रा में डेटा शामिल है, सिस्टम मेमोरी की तुलना में बहुत बड़ा है।

मैं एक मौजूदा कोड काम कर रहा हूं जिसे मैं सुधारने की कोशिश करता हूं (डिजाइन, संभव मुद्दे, प्रदर्शन, आदि)। यह कोड केवल 4KB रैम के साथ पुराने 8bit MCU पर चलता है । इस कोड में मैं एक 4KB रैम सिस्टम पर लगभग 1KB (हाँ, 1KB ) के एक सरणी के उपयोग का सामना करता हूं । इस सरणी के प्रत्येक बाइट का उपयोग किया जाता है, यह सवाल नहीं है। समस्या यह है कि यह सरणी उस फ़ाइल में एक स्थिर सरणी है जहां इसे घोषित किया गया है, इसलिए इसका जीवन चक्र कार्यक्रम एक के समान है (अर्थात अनंत माना जा सकता है)।

हालाँकि, कोड को पढ़ने के बाद, मुझे पता चला कि इस सरणी को अनंत जीवन चक्र की कोई आवश्यकता नहीं है, यह पूरी तरह से प्रक्रियात्मक तरीके से बनाया और निपटा है, इसलिए हमें इसे केवल उस फ़ंक्शन में घोषित करने में सक्षम होना चाहिए जहां इसका उपयोग किया जाता है, इस तरह यह स्टैक पर होगा, और इसलिए हम इस 1KB रैम को बचाएंगे।

अब सवाल: क्या यह एक अच्छा विचार होगा? डिज़ाइन के दृष्टिकोण से, यदि इसे अनंत / वैश्विक जीवनचक्र की आवश्यकता नहीं है, तो यह स्टैक के अंतर्गत आता है। लेकिन हे, कि 4KB में से 1KB है, क्या इस तरह 25% RAM आवंटित करने का कोई दोष नहीं है? (यह स्टैक का 50% या अधिक हो सकता है)

क्या कोई इस तरह की स्थिति के साथ कुछ अनुभव साझा कर सकता है, या कोई व्यक्ति इस सरणी को स्टैक पर नहीं रखने के लिए किसी वैध कारण के बारे में सोचता है? मैं तकनीकी कमियों के साथ-साथ डिजाइन पर टिप्पणियों की तलाश कर रहा हूं।

केवल एक चीज जो मैं सचेत हूं वह यह है कि मुझे यह सुनिश्चित करना है कि इस समारोह में प्रवेश करते समय मेरे पास वास्तव में 1KB स्टैक फ्री हो। शायद यही सब मुझे ध्यान रखना है, शायद नहीं।


4
आपने लिखा, "और इसलिए इस 1KB RAM को बचाएं"। इसे किस लिए बचाएं? उस 1KB को उपलब्ध होना चाहिए जब आपको सरणी के लिए इसकी आवश्यकता होती है तो एक स्थैतिक आवंटन क्यों नहीं? क्या आपके पास मेमोरी के लिए एक और उपयोग है जब यह सरणी के लिए आवश्यक नहीं है?
kkrambo

@kkrambo कुछ बिंदु पर हम मानते हैं कि एक सिस्टम भरा हुआ है जब हम रैम पर कुछ भी नहीं जोड़ सकते हैं, चाहे वह कुछ स्थिर हो या स्टैक पर। यदि हम इस सरणी को केवल तभी उपयोग करते हैं, जब हम इसका उपयोग करते हैं, यह एक और कार्यक्षमता के लिए जगह देता है जब तक कि वे एक ही समय में उपयोग नहीं किए जाते हैं। लेकिन सवाल पूरी तरह से वैध है, फिलहाल अगर हम SW में कुछ भी नहीं बदलते हैं, तो हमें अधिक RAM की आवश्यकता नहीं है;)
टिम

1
क्या आप स्पष्ट कर सकते हैं कि क्या इस एरे में ऐसी सामग्री है जो हमेशा एक जैसी रहती है या यदि यह बदल जाता है तो इसका उपयोग करने वाले फ़ंक्शन को लागू किया जाता है?
ब्लरफ्ल ऑक्ट

@Blrfl यह फ़ंक्शन कहा जाता है हर बार बदलता है।
टिम

जवाबों:


8

केवल एक चीज जो मैं सचेत हूं वह यह है कि मुझे यह सुनिश्चित करना है कि इस समारोह में प्रवेश करते समय मेरे पास वास्तव में 1KB स्टैक फ्री हो।

हाँ, और यह एक मजबूत बाधा है। आप स्टैक पर उपलब्ध इतने बड़े स्थान को प्राप्त करने से बेहतर होगा कि आप सांख्यिकीय रूप से सुनिश्चित हों। यदि कोड छोटा है, यदि आप अपने कोड को संकलित करने के लिए हाल ही में GCC का उपयोग कर रहे हैं, तो यह देखें ।

BTW, कुछ सस्ते माइक्रोप्रोसेसर "बड़े" कॉल फ्रेम का उपयोग "सामान्य" एक की तुलना में अधिक महंगा कर सकते हैं (जैसे कि उनका निर्देश सेट स्टैक पॉइंटर से एक-बाइट ऑफसेट का पक्ष लेंगे)। YMMV।

इसके अलावा, यदि आप C में कोडिंग कर रहे हैं और यदि आपको लगता है कि आपके बड़े सरणी का अन्य प्रयोजनों के लिए उपयोग किया जा सकता है, तो आप इसे यूनियन सदस्य ( unionप्रकार का वैश्विक चर के साथ ) बनाने पर विचार कर सकते हैं । हां, यह काफी बदसूरत है।

वैकल्पिक रूप से, आप अपने आवेदन के लिए उपयुक्त कुछ आदिम ढेर आवंटन कोडिंग पर विचार कर सकते हैं (और इसमें एपीआई अलग mallocऔर free.... हो सकता है )।


1
धन्यवाद, मैं वास्तव में इस तरह के जवाब की उम्मीद कर रहा था, यानी इसे वैधानिक रूप से आवंटित किया जाए ताकि यह सुनिश्चित हो कि मैं एक स्टैक ओवरफ्लो के साथ समाप्त नहीं हो। दुर्भाग्य से मेरे पास हाल ही में जीसीसी संकलक नहीं है और कोड छोटा नहीं है।
टिम

क्या आप अपने प्लेटफॉर्म के लिए जीसीसी संकलक से (शायद जीसीसी को उसके स्रोत कोड से संकलन करके) प्राप्त कर सकते हैं?
बेसिल स्टारीनेविच

2
मेरे पास पहले से ही एक है, यह वास्तव में पुराना है। एक नए पर काम करना मेरे दायरे में नहीं है, न ही यह मेरे कार्यक्रम में फिट होगा। लेकिन निश्चित रूप से, कुछ चीजें अप टू डेट टूल के साथ आसान होंगी।
टिम

3
अपने बॉस से आपको एक नया जीसीसी प्राप्त करने के लिए कहना (या तो आपको द्विआधारी उपकरण प्रदान करने के लिए, या आपको जीसीसी के पुनर्मूल्यांकन के लिए समय देकर) आईएमएचओ सार्थक है, क्योंकि संभवत: नए जीसीसी थोड़ा बेहतर अनुकूलन करेंगे (क्या आप जानते हैं gcc -flto -Os? ) और आपको कुछ स्मृति प्राप्त हो सकती है ....
बासिल स्टायरनविच

2
यह पटरी पर है, लेकिन थोड़ी देर पहले नहीं आएगा। मैं पहले से ही अधिक हाल के टूलचिन्स के साथ अन्य प्रणालियों पर -OOS का उपयोग करता हूं, लेकिन मुझे इस -flto पैरामीटर के बारे में पता नहीं था, इसे इंगित करने के लिए धन्यवाद। (ध्यान दें कि मैंने कुछ सप्ताह पहले GCC -OO और -O1-3 पैरामीटर के साथ GCC 5.4.1 पर कुछ परीक्षण किए हैं और RAM हर समय एक ही था। FLASH और MCU रनिंग समय हालांकि अलग थे। यह उसी MCU पर नहीं था जैसा कि मैंने इस Q / A में उल्लेख किया है)
टिम

6

लोग एक बड़े स्टैक के साथ सतर्क रहते हैं, क्योंकि यह रैम में पीछे की ओर बढ़ता है और चर के मूल्यों को अधिलेखित करता है, जिससे अस्पष्ट व्यवहार होता है। यह और भी बदतर हो जाता है, क्योंकि आपको सबसे कम संभव स्टैक पॉइंटर पता जानना होगा और रूटीन में प्रवेश करने पर आवंटित करने के लिए आकार को घटाना होगा।

हार्डवेयर मेमोरी प्रबंधन के लिए यह सब एक काम है (स्टैक ओवरफ्लो होने पर जाल या दोष उत्पन्न करना चाहिए) या कंपाइलर के लिए, इस तरह के विश्लेषण के लिए इसमें विशेषताएं हैं।

अन्यथा, आप वही कर सकते हैं जो आप अपनी रैम के साथ चाहते हैं।


4

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

संघ के साथ कुछ अन्य डेटा के साथ ब्लॉक साझा करने का सुझाव आईएमओ मान्य है, हालांकि यह हार्ड-टू-फाइंड समस्याओं का स्रोत भी हो सकता है, अगर आप इसमें गलत चर का पता लगाते हैं।

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


1

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


1
मैंने अतीत में भी ऐसा किया है, लेकिन मेरा प्रश्न उन समस्याओं के बारे में अधिक था जो अगर मैं इसे स्टैक पर रख सकता हूं, तो वास्तव में रैम के विकल्प के बारे में नहीं जब हम इसके बारे में कम होते हैं। वैसे भी जवाब देने के लिए धन्यवाद
टिम

1

विशेष रूप से जब एम्बेडेड सिस्टम के साथ काम करते हैं, तो आप संकलन समय पर होने वाली संभावित विफलताओं में से बहुत कुछ चाहते हैं और कुछ भी कभी भी विफल रहता है (अच्छा समय यदि हम इसे प्राप्त कर सकते हैं, हालांकि ...)।

बड़ी संख्या में ऐरे बनाने से आपको अपने कार्यक्रम के मनमाने ढंग से राज्यों को आवंटित करने की आवश्यकता हो सकती है, जो वास्तव में आवंटित किया गया है - लिंकर अंततः आपको चेतावनी देगा "यह रैम में फिट नहीं होता है", जबकि स्टैक आवंटन बस आपके प्रोग्राम को हार्ड-टू-डिबग स्टैक के साथ क्रैश कर देगा। अतिप्रवाह।

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