हमें ढेर की आवश्यकता क्यों है यदि सब कुछ स्टैक पर अधिक कुशलता से किया जा सकता है?


24

यह वास्तव में कुछ इस सवाल से संबंधित है जो मैंने कल के बारे में पूछा था कि आज हम उपयोग किए जाने वाले अनुप्रयोगों में एक स्टैक और हीप दोनों क्यों आवश्यक हैं (और क्यों हम एक सरल के लिए दोनों के बजाय एक हीप के साथ नहीं जा सकते हैं; द्वारा जाना विलक्षण मानक)।

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


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

2
आपका आधार दोषपूर्ण है - सब कुछ स्टैक पर अधिक कुशलता से नहीं किया जा सकता है। कि क्या - यह जवाब आप प्राप्त करने के लिए कोई विरोधाभास नहीं है सकते हैं ढेर पर किया जाना बहुत तेजी से वहाँ किया जा सकता है।
ingo

... यह मानते हुए कि आपके हार्डवेयर में स्टैक, या स्टैक-रिलेटिव एड्रेसिंग है।
रिच मेल्टन

3
मैं सहमत हूं। मैं कहता हूं कि करो।
जेएफओ

जवाबों:


25

ढेर के साथ समस्या यह है कि आप मेमोरी को "मुक्त" नहीं कर सकते हैं जब तक कि यह स्टैक के शीर्ष पर न हो। उदाहरण के लिए, मान लें कि आपने अलग-अलग आकार की 3 चीजें आवंटित की हैं:

a = allocate(2000000); // 2000000 bytes
b = allocate(1);
c = allocate(5000000);

स्टैक aनीचे, bमध्य और cशीर्ष पर होगा। यदि हम मुक्त करना चाहते हैं तो यह समस्याग्रस्त हो जाता है b:

free(b); // b is not on top! We have to wait until c is freed!

वर्कअराउंड सभी डेटा को स्थानांतरित करने और स्थानांतरित करने के लिए है, bताकि यह बाद में आए a। यह काम करता है, लेकिन इस मामले में 5000000 प्रतियों की आवश्यकता होगी - ऐसा कुछ जो ढेर की तुलना में बहुत धीमा होगा।

यही कारण है कि हमारे पास एक ढेर है। हालांकि आवंटन स्टैक की तुलना में धीमा हो सकता है ( O(log n)बनाम O(1)), ढेर एक अनियंत्रित स्थान पर स्मृति को तेजी से मुक्त करने की अनुमति देता है - O(log n)एक स्टैक की तुलना मेंO(n)


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

खैर, फेसबुक के डिस्क को ढेर के रूप में देखा जा सकता है। और मुझे पूरा यकीन है कि उनके पास थोज़ डिस्क के लिए किसी तरह का कचरा संग्रह है।
deadalnix

2
@deadalnix दरअसल वह ढेर के बजाय एक विशाल ढेर का उपयोग करने का एक उदाहरण है जो आमतौर पर बड़ी मात्रा में स्मृति के लिए उपयोग किया जाता है। फेसबुक एक विशेष मामला है। डेटा को इतनी तेजी से जोड़ा जाता है कि यह हटा दिया जाता है कि डीलक्लोकेशन की वृद्धि दर में कोई फर्क नहीं पड़ता है - आप उस ओ (1) आवंटन को प्राप्त करने के लिए डिज़ाइन में मेमोरी लीक को जानबूझकर शामिल कर सकते हैं।
टॉम क्लार्कसन

7
@PaulTomblin FB का मुख्य कारण सामग्री को हटाया नहीं जाता है ताकि वे इसे अपने लाभ के लिए उपयोग कर सकें ...
quant_dev

5
Facebook doesn't remove content from its disk when you ask it to remove it, it just removes the pointer to it- जो अनिवार्य रूप से तब होता है जब आप किसी ऑपरेटिंग सिस्टम पर फ़ाइल को साधारण डिलीट करते हैं।
रॉबर्ट हार्वे

5

स्टैक प्रति-धागा है, हीप प्रक्रिया-चौड़ा है

यदि 100 धागे सभी प्रसंस्करण कार्य आइटम हैं जिन्हें मैंने एक कतार में रखा है, तो वास्तव में मैं काम की वस्तुओं को कहां आवंटित करता हूं ताकि 100 धागे में से कोई भी उन्हें देख सके?

स्मृति के अन्य प्रकार भी हैं

उदाहरण के लिए स्मृति-मैप की गई फ़ाइलें, साझा की गई मेमोरी, I / O मैप्ड (कर्नेल मोड)। इन स्थितियों में दक्षता का तर्क एक प्रकार की लूट है।


4

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


3
LIFO, FIFO नहीं।
Pubby

कभी-कभी इसे
फिलो

3

स्टैक मेमोरी आवंटन के लिए बहुत अच्छा काम करता है जो लास्ट इन फर्स्ट आउट (LIFO) नियमों का पालन करता है, अर्थात, आप मेमोरी को उस रिवर्स रिवर्स ऑर्डर में मुक्त करते हैं जो आप इसे आवंटित करते हैं। LIFO एक बहुत ही सामान्य, शायद सबसे आम, स्मृति आवंटन पैटर्न है। लेकिन यह एकमात्र पैटर्न नहीं है, या केवल सामान्य पैटर्न भी नहीं है। कुशल कार्यक्रम लिखने के लिए जो हमें कई सामान्य समस्याओं के लिए भत्ता बनाना पड़ता है, भले ही यह कम जटिल पैटर्न हो, भले ही इसका मतलब अधिक जटिल घुसपैठ हो।

अगर मैं एक पैराग्राफ के लिए सभी मेटा प्राप्त कर सकता हूं: आप एक शुरुआत हैं, एक शुरुआत के रूप में आप सादगी, और काले और सफेद नियमों को महत्व देते हैं। हालाँकि, एक शुरुआत के रूप में आपके पास समस्याओं और बाधाओं की सीमा का केवल एक झाँका दृश्य है जिसे कंप्यूटर प्रोग्राम द्वारा समायोजित किया जाना है। आप एक ऐसी तकनीक में प्रवेश कर रहे हैं जो 75 वर्षों से चल रही है। यह पूछने में कुछ भी गलत नहीं है कि चीजें किस तरह से हैं, लेकिन जवाब आम तौर पर होने वाला है "हाँ, हमने 50 साल पहले सरल, सीधे-आगे की विधि की कोशिश की थी और यह पूरी कक्षाओं के लिए बहुत अच्छा काम नहीं कर रहा था। समस्याओं का, इसलिए हमें कुछ और जटिल करना पड़ा "। एक प्रौद्योगिकी के रूप में सादगी आम तौर पर दक्षता और लचीलेपन के लिए रास्ता देना है।


0

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


0

ढेर भंडारण आवंटित करने के कई अन्य कारणों के बीच।

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

आप अपने फ़ंक्शन से आपके द्वारा कॉल किए जाने वाले फ़ंक्शंस में स्टैक आइटम के पते पास कर सकते हैं, क्योंकि आप गारंटी दे सकते हैं कि वे आपके प्रोग्राम "रिटर्न ()" तक मौजूद रहेंगे। लेकिन जैसे ही आपका फ़ंक्शन लौटाता है, सभी स्टैक स्टोरेज को पकड़ लेता है।

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