कितना स्टैक उपयोग बहुत अधिक है?


22

हाल ही में जब मैं C या C ++ लिख रहा होता हूं, तो मैं अपने सभी चरों को स्टैक पर घोषित करूंगा क्योंकि यह जावा के विपरीत एक विकल्प है।

हालांकि, मैंने सुना है कि स्टैक पर बड़ी चीजों की घोषणा करना एक बुरा विचार है।

  1. आखिर ऐसा क्यों है? मुझे लगता है कि स्टैक ओवरफ्लो शामिल है, लेकिन मैं बहुत स्पष्ट नहीं हूं कि ऐसा क्यों होता है।
  2. स्टैक पर कितना सामान बहुत अधिक है?

मैं स्टैक पर 100MB फाइलें डालने की कोशिश नहीं कर रहा हूं, स्ट्रिंग बफ़र्स या जो भी उपयोग करने के लिए बस एक दर्जन किलोबाइट सरणियां हैं। क्या यह बहुत अधिक स्टैक उपयोग है?

(क्षमा करें यदि डुप्लिकेट है, तो स्टैक की खोज करना स्टैक ओवरफ्लो का संदर्भ देता है। यहां तक ​​कि कॉल स्टैक टैग भी नहीं है, मैंने सिर्फ सार का उपयोग किया है।)


1
आप "स्टैक पर 100 एमबी फाइलें कैसे डालते हैं"? बफर और कंटेनर कार्यान्वयन (और std :: string की तरह) आमतौर पर अपने पेलोड को स्टोर करने के लिए ढेर का उपयोग करते हैं।
मर्फी

2
आप प्रति फ़ंक्शन / विधि का एक उचित मात्रा में रिकार्शन शामिल होने तक प्राप्त कर सकते हैं, फिर आप अपनी क्षमताओं को गंभीर रूप से सीमित कर रहे हैं, विज़-ए-विज़ पुनरावर्ती गहराई को सीमित कर रहे हैं, इसलिए पुनरावर्ती कार्यों के भीतर, आप बहुत कम स्थानीय उपयोग करना चाहते हैं संभव के रूप में चर / ढेर अंतरिक्ष।
एरिक Eidt

3
ध्यान दें कि C & C ++ अलग हैं। एक स्थानीय std::vector<int>वैरिएबल ढेर जगह नहीं खाएगा, अधिकांश डेटा ढेर में है।
बेसिल स्टारीनेवविच

जवाबों:


18

यह आपके ऑपरेटिंग सिस्टम पर निर्भर करता है। विंडोज पर, स्टैक के लिए विशिष्ट अधिकतम आकार 1 एमबी है, जबकि यह एक विशिष्ट आधुनिक लिनक्स पर 8 एमबी है, हालांकि उन मूल्यों को विभिन्न तरीकों से समायोज्य है। यदि पूरे कॉल स्टैक में आपके स्टैक चर (निम्न स्तर के ओवरहेड जैसे रिटर्न एड्रेस, स्टैक-आधारित तर्क, रिटर्न वैल्यू प्लेसहोल्डर और अलाइनमेंट बाइट्स) का योग उस सीमा से अधिक हो जाता है, तो आपको एक स्टैक ओवरफ्लो मिलता है, जो आमतौर पर आपका ले लेता है वसूली में किसी भी मौका के बिना कार्यक्रम।

कुछ किलोबाइट आमतौर पर ठीक होते हैं। दस किलोबाइट खतरनाक है क्योंकि यह योग करना शुरू कर देता है। सैकड़ों किलोबाइट बहुत बुरा विचार है।


1
क्या 2016 में सामान्य स्टैक सीमा कई मेगाबाइट (यानी आमतौर पर एक से अधिक, लेकिन शायद एक दर्जन से कम) नहीं है? मेरे लिनक्स डेस्कटॉप पर, यह डिफ़ॉल्ट रूप से 8Mbytes है ...
Basile Starynkevitch

"ऑन ... ...] लिनक्स, एक स्टैक के लिए विशिष्ट अधिकतम आकार 1 एमबी है" $ ulimit -aमेरे सिस्टम पर दूसरों के बीच रिटर्न देता है stack size (kbytes, -s) 8192
मर्फी

9

एकमात्र मान्य उत्तर अस्पष्ट है: "बहुत अधिक है जब स्टैक ओवरफ्लो होता है।"

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

void break_the_camels_back()
{
    int straw;
    ...
}

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

आपके पास कुछ विकल्प हैं। पहले यह अनुमान लगाना नहीं है कि कितना स्टैक उपलब्ध है और सिस्टम से पूछें। POSIX के अनुरूप कुछ भी एक getrlimit(2)फ़ंक्शन होगा जो आपको ऊपरी सीमा बताएगा। RLIMIT_STACKवह विशिष्ट सीमा है जो आप चाहते हैं। दूसरा यह मॉनिटर करना है कि आपके प्रोग्राम कितने स्टैक का उपयोग कर रहे हैं और इसके आधार पर स्वचालित चर बनाम डायनामिक मेमोरी आवंटन के बारे में निर्णय लें। जहां तक ​​मुझे पता है, स्टैक का कितना उपयोग किया जाता है, यह निर्धारित करने के लिए कोई मानक कार्य नहीं है, लेकिन जैसे प्रोग्राम valgrindआपके लिए इसका विश्लेषण कर सकते हैं।


4

यदि आप स्टैक पर 10,000 बाइट्स का एक सरणी आवंटित करते हैं, तो वह सरणी आकार में सीमित है। 10,000 बहुत हो सकता है, लेकिन अगर आपको 10,001 बाइट्स की आवश्यकता है, तो आपका प्रोग्राम क्रैश या खराब हो सकता है। तो इस स्थिति में, आप कुछ ऐसा चाहते हैं जो आपकी ज़रूरत के आकार के अनुरूप हो, और यह कुछ स्टैक पर नहीं होगा।

स्टैक पर स्ट्रिंग बफ़र्स के लिए निश्चित आकार के सरणियाँ एक समस्या नहीं हैं क्योंकि वे स्टैक पर मेमोरी रखते हैं, वे एक समस्या हैं क्योंकि निश्चित आकार के बफ़र्स होने के लिए एक घातक समस्या है।

लेकिन अगर आप C ++ का उपयोग करते हैं, और उदाहरण के लिए एक std :: string या std :: vec को स्टैक पर घोषित करते हैं, तो स्टैक पर जो है वह वास्तव में एक निश्चित और छोटे आकार का होगा। वास्तविक डेटा को ढेर पर संग्रहीत किया जाएगा। आप एक std :: string उदाहरण में एक लाख वर्ण संग्रहीत कर सकते हैं, और यह केवल ढेर पर डेटा (आमतौर पर 8 से 24 बाइट्स, कार्यान्वयन पर निर्भर करता है) और ढेर पर एक लाख बाइट्स लेगा।


2

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

महत्वपूर्ण बात यह है कि स्टैक पर कच्चे मेम के बड़े टुकड़ों को चार [जैसे * 1024 * 1024] पर न डालें और ढेर आवंटन को लपेटने के लिए कक्षाएं डिजाइन करें और स्टैक का उपयोग केवल स्वचालित रूप से विध्वंसक को कॉल करने की सुविधा के लिए करें।

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