2009-10-11 12 views
22

संभव डुप्लिकेट:
When is it best to use a Stack instead of a Heap and vice versa?आप ढेर के बजाय ढेर पर स्मृति आवंटित क्यों करना चाहते हैं?

मैं ढेर ढेर बनाम के बारे में अन्य प्रश्न के कुछ पढ़ा है, लेकिन वे क्या ढेर/ढेर क्यों बजाय कर पर अधिक ध्यान केंद्रित करने लगते हैं आप उनका इस्तेमाल करेंगे।

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

क्या स्टैक आवंटन के बजाय ढेर आवंटन का उपयोग करने के अन्य कारण हैं जिन्हें मुझे पता नहीं है?

+1

डुप्लिकेट: http://stackoverflow.com/questions/102009/when-is-it-best-to-use-a-stack-instead-of-a-heap-and-vice-versa – Naveen

+6

@ नवीन: सॉर्टा - दूसरा एक सी ++ प्रश्न है जहां यह सी है, इसलिए कुछ जवाब 'हटाएं' और 'नया' पर चर्चा करते हैं जो सी –

उत्तर

36

ऐसे कुछ कारण हैं:

  • मुख्य एक है कि ढेर आवंटन के साथ, आप वस्तु के जीवनकाल (malloc/calloc से free करने के लिए) पर सबसे अधिक लचीला नियंत्रण है है;
  • स्टैक स्पेस आमतौर पर ढेर स्पेस से अधिक सीमित संसाधन है, कम से कम डिफ़ॉल्ट कॉन्फ़िगरेशन में;
  • ढेर अंतरिक्ष आवंटित करने में विफलता को अच्छी तरह से संभाला जा सकता है, जबकि स्टैक स्पेस से बाहर चलना अक्सर अप्राप्य होता है।

लचीला ऑब्जेक्ट जीवनकाल के बिना, बाइनरी पेड़ और लिंक्ड सूचियों जैसे उपयोगी डेटा संरचनाएं लिखना लगभग असंभव होगा।

4

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

19
  1. आप एक आवंटन एक समारोह मंगलाचरण
  2. आप ढेर अंतरिक्ष (जो आमतौर पर कुछ एमबीएस तक सीमित है)
  3. आप फिर से locatable स्मृति साथ काम कर रहे (Win16 बचाकर रखना चाहते हैं परे जीना चाहते हैं डेटाबेस, आदि), या आवंटन विफलताओं से पुनर्प्राप्त करना चाहते हैं।
  4. परिवर्तनीय लंबाई कुछ भी। आप इसके चारों ओर नकली कर सकते हैं, लेकिन आपका कोड वास्तव में बुरा होगा।

बड़ा वाला # 1 है। जैसे ही आप किसी भी तरह की सहमति या आईपीसी # 1 में आते हैं, हर जगह है। यहां तक ​​कि सबसे गैर-तुच्छ एकल एकल थ्रेडेड अनुप्रयोग कुछ ढेर आवंटन के बिना तैयार करने के लिए मुश्किल हैं। वह व्यावहारिक रूप से सी/सी ++ में एक कार्यात्मक भाषा फिक्र करना होगा।

8

तो मैं एक स्ट्रिंग बनाना चाहता हूं। मैं इसे ढेर या ढेर पर बना सकता हूं।के दोनों कोशिश करते हैं:

char *heap = malloc(14); 
if(heap == NULL) 
    { 
    // bad things happened! 
    } 
strcat(heap, "Hello, world!"); 

और ढेर के लिए:

char stack[] = "Hello, world!"; 

तो अब मैं उनके संबंधित स्थानों में इन दो तार की है। बाद में, मैं उन्हें लंबे समय तक बनाना चाहते:

char *tmp = realloc(heap, 20); 
if(tmp == NULL) 
    { 
    // bad things happened! 
    } 
heap = tmp; 
memmove(heap + 13, heap + 7); 
memcpy(heap + 7, "cruel ", 6); 

और ढेर के लिए:

// umm... What? 

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

char username[MAX_BUF_SIZE]; 
3

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

0

बस जोड़ने के लिए आप alloca उपयोग कर सकते हैं ढेर पर स्मृति को आबंटित करने के लिए, लेकिन फिर से ढेर पर स्मृति सीमित है और भी अंतरिक्ष केवल समारोह निष्पादन केवल दौरान मौजूद है। जिसका मतलब यह नहीं है कि ढेर पर सब कुछ आवंटित किया जाना चाहिए। सभी design decisions की तरह यह कुछ मुश्किल भी है, दोनों का "न्यायसंगत" संयोजन इस्तेमाल किया जाना चाहिए।

+0

पर लागू नहीं होते हैं। एक बार फिर मुझे "फ़ंक्शन' x() 'एक गैर मानक कार्य "टिप्पणी। 'alloca()' कुछ रूपों या किसी अन्य प्लेटफ़ॉर्म पर कई प्लेटफॉर्म पर पाया जाता है, लेकिन यह किसी भी मानक का हिस्सा नहीं है। –

+0

क्रिस: यह बिल्कुल सही है, हालांकि ढेर बनाम ढेर आवंटन की व्यापक चर्चा के संदर्भ में, कुछ स्थानों पर 'एलोका()' का अस्तित्व विचार करने के लिए उपयोगी है। विशेष रूप से क्योंकि यह अच्छी तरह से दिखाता है कि आवंटन आकार की रनटाइम गणना पर सीमा सी द्वारा लगाया गया प्रतिबंध है, जो स्टैक-आधारित आवंटन के विचार से निहित कुछ नहीं है। – caf

0

(जो आप का उल्लेख) वस्तु के जीवन का मार्गदर्शन नियंत्रण इसके अलावा, ढेर उपयोग करने के लिए अन्य कारणों में शामिल हैं:

  • वस्तु के आकार से अधिक रन-समय नियंत्रण (दोनों प्रारंभिक आकार और यह "बाद में" आकार, के दौरान कार्यक्रम का निष्पादन)।

उदाहरण के लिए, आप निश्चित आकार की एक सरणी आवंटित कर सकते हैं, जिसे केवल रन टाइम पर जाना जाता है।

सी 99 में वीएलए (परिवर्तनीय लंबाई Arrays) की शुरूआत के साथ, ढेर का उपयोग किए बिना निश्चित रन-टाइम आकार के सरणी आवंटित करना संभव हो गया (यह मूल रूप से 'एलोका' कार्यक्षमता का एक भाषा-स्तर कार्यान्वयन है)। हालांकि, अन्य मामलों में आपको अभी भी सी 99 में ढेर की आवश्यकता होगी।

  • ऑब्जेक्ट्स की कुल संख्या पर रन-टाइम नियंत्रण।

उदाहरण के लिए, जब आप एक बाइनरी पेड़ स्टक्चर बनाते हैं, तो आप अर्थात् पेड़ के नोड्स को पहले से ही स्टैक पर आवंटित नहीं कर सकते हैं। आपको "मांग पर" आवंटित करने के लिए ढेर का उपयोग करना होगा।

  • कम स्तरीय तकनीकी विचार, सीमित स्टैक स्पेस के रूप में (दूसरों ने पहले ही इसका उल्लेख किया है)।

जब आप भी कम समय (एक समारोह के अंदर) के लिए एक बड़े, कहते हैं, मैं/हे बफर की जरूरत है, यह बजाय एक बड़ी स्वचालित सरणी की घोषणा के ढेर से यह अनुरोध करने के लिए और अधिक समझ में आता है।

0

स्टैक वैरिएबल (जिन्हें अक्सर 'स्वचालित चर' कहा जाता है) का सबसे अच्छा उपयोग उन चीजों के लिए किया जाता है, जिन्हें आप हमेशा एक जैसा होना चाहते हैं, और हमेशा छोटे होते हैं।

int x; 
char foo[32]; 

सभी स्टैक आवंटन हैं, ये संकलन समय पर भी तय किए गए हैं।

ढेर आवंटन का सबसे अच्छा कारण यह है कि आप हमेशा यह नहीं जानते कि आपको कितनी जगह चाहिए। एक बार कार्यक्रम चलने के बाद आप अक्सर यह जानते हैं। आपके पास सीमाओं का विचार हो सकता है लेकिन आप केवल आवश्यक स्थान की सटीक मात्रा का उपयोग करना चाहते हैं।

आप एक फ़ाइल है कि 50MB के 1k से कुछ भी हो सकता में पढ़ने के लिए किया था, तो आप ऐसा नहीं होगा: -

int readdata (FILE * f) { 
    char inputdata[50*1024*1025]; 
    ... 
    return x; 
} 

कि ढेर, जो आमतौर पर के रूप में विफल हो जाएगा पर 50MB आवंटित करने की कोशिश करेगा ढेर आमतौर पर 256k तक सीमित है।

0

ढेर और ढेर एक ही "खुली" मेमोरी स्पेस साझा करते हैं और अंततः स्मृति के पूरे खंड का उपयोग करते समय, वे एक बिंदु पर आते हैं, जहां वे मिलते हैं। उस स्थान के बीच संतुलन को बनाए रखना जो उनमें से प्रत्येक का उपयोग आवंटन लागत के बाद आवंटित लागत और स्मृति के डी-आवंटन को एक छोटा एसिम्प्टोटिक मूल्य होगा।

संबंधित मुद्दे