2010-07-17 14 views
5

इसके बीच क्या अंतर है:सी ++: स्थानीय सरणी परिभाषा बनाम एक मॉलोक कॉल

somefunction() { 
    ... 
    char *output; 
    output = (char *) malloc((len * 2) + 1); 
    ... 
} 

और यह:

somefunction() { 
    ... 
    char output[(len * 2) + 1]; 
    ... 
} 

एक दूसरे से अधिक उचित कब होता है?

सभी आपके उत्तरों के लिए धन्यवाद। यहां सारांश है:

  1. ex। 1 ढेर आवंटन
  2. पूर्व है। 2 स्टैक आवंटन
  3. स्टैक पर एक आकार सीमा है, इसे छोटे आवंटन के लिए उपयोग करें
  4. आपको ढेर आवंटन मुक्त करना होगा, या यह
  5. को रिसाव करेगा, फ़ंक्शन आवंटित होने पर स्टैक आवंटन पहुंच योग्य नहीं होगा
  6. ढेर आवंटन तब तक पहुंच योग्य है जब तक आप इसे मुक्त नहीं करते (या ऐप समाप्त होता है)
  7. वीएलए मानक सी ++

सुधार का हिस्सा नहीं है।

यहां ढेर बनाम स्टैक के बीच अंतर का कुछ स्पष्टीकरण है:
What and where are the stack and heap?

+0

आपको अपनी सी ++ पुस्तक से परामर्श लेना चाहिए। यदि आपके पास सी ++ पुस्तक नहीं है, तो मैं [पूर्ण सी ++ पुस्तक मार्गदर्शिका और सूची] में सूचीबद्ध शुरुआती ग्रंथों में से एक प्राप्त करने की अनुशंसा करता हूं (http://stackoverflow.com/questions/388242/the-definitive-c-book -मार्गदर्शक और सूची)। –

+4

इसके अलावा, सवाल पूरी तरह से निर्भर करता है कि कैसे 'लेन' परिभाषित किया गया है; यदि यह स्थिर नहीं है, तो दूसरा कोड उदाहरण बीमार गठित सी ++ है। –

+0

लेन एक int है और फ़ंक्शन के अंदर स्ट्रेल के परिणाम के लिए असाइन किया गया है। – Gush

उत्तर

5

स्थानीय लोगों का उपयोग करें जब आपके पास केवल थोड़ी सी मात्रा हो, और आप उस फ़ंक्शन के दायरे के बाहर डेटा का उपयोग नहीं करेंगे, जिसे आपने घोषित किया है। यदि आप डेटा को पास करने जा रहे हैं, तो malloc।

स्थानीय चर ढेर पर आयोजित किए जाते हैं, जो ढेर से अधिक आकार सीमित है, जहां मॉलोक के साथ आवंटित सरणी जाती है। मैं आमतौर पर कुछ भी के लिए जाता हूं> ढेर पर 16 बाइट लगाए जाते हैं, लेकिन आपके पास इससे थोड़ा अधिक लचीलापन होता है। बस केबी/एमबी आकार सीमा में स्थानीय आवंटित न करें - वे ढेर पर हैं।

+2

+1, लेकिन मुझे लगता है कि 16 बाइट थोड़ा कम है। मेगाबाइट्स में अधिकांश प्लेटफ़ॉर्म पर डिफ़ॉल्ट स्टैक आकार नहीं है (इसलिए अधिकांश मामलों में बहु-केबी चर ठीक होना चाहिए)? –

+0

हां, लेकिन जब आप ढेर पर आवंटित करते हैं, तो आपको डेटा के जीवनकाल के साथ-साथ आकार के बारे में भी विचार करना चाहिए। मेरा मतलब उन मानों के लिए 16 बाइट था जिनके जीवनकाल ज्ञात नहीं हो सकते हैं। आप ढेर पर कई केबी आवंटित कर सकते हैं, फिर किसी अन्य फ़ंक्शन में बंद कर सकते हैं, जो कई केबी आवंटित करता है, और इसी तरह - यह जल्दी से भर सकता है। (StackedCrooked की प्रतिक्रिया में इसे और अधिक चर्चा की।) –

+3

चूंकि सवाल सी ++ के बारे में है, इसलिए मैं मॉलोक का उपयोग करने की सिफारिश का जोरदार विरोध करता हूं। सी में, मॉलोक का उपयोग करें। सी ++ में, नया उपयोग करें। –

6

ढेर पर पहले आबंटित करता स्मृति:

यहां ढेर बनाम ढेर के बीच अंतर के कुछ व्याख्या है। आपको स्मृति को मुक्त करना याद रखना होगा, या यह रिसाव होगा। यह उचित है अगर स्मृति को फ़ंक्शन के बाहर उपयोग करने की आवश्यकता है, या यदि आपको बड़ी मात्रा में स्मृति आवंटित करने की आवश्यकता है।

दूसरा स्टैक पर स्मृति आवंटित करता है। फ़ंक्शन लौटने पर इसे स्वचालित रूप से पुनः प्राप्त किया जाएगा। यदि आपको अपने कॉलर को मेमोरी वापस करने की आवश्यकता नहीं है तो यह सबसे सुविधाजनक है।

+1

दूसरी ओर, आप ढेर पर बहुत अधिक नहीं रखना चाहते हैं, क्योंकि यह ढेर के रूप में बड़ा नहीं है। तो, 'int डेटा [10]' ठीक है, लेकिन मैं 'int डेटा [10000]' पर काम नहीं कर रहा हूं। स्टैक की आकार सीमाओं का उल्लेख करने के लिए – zvone

5

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

इस प्रश्न में कोड के साथ कई अन्य अजीब चीजें भी चल रही हैं। सबसे पहले, यह इस एक C++ कार्यक्रम है, आप() ताकि आप कहेंगे

output = new char[len+1]; 

और क्या लेन * 2 + 1 वैसे भी साथ है malloc के बजाय नया प्रयोग करना चाहते हैं?हो सकता है कि यह आपके कोड में कुछ खास है, लेकिन मुझे लगता है कि आप यूनिकोड वर्ण या मल्टीबाइट वर्ण आवंटित करना चाहते हैं। यदि यह यूनिकोड है, तो शून्य समाप्ति दो बाइट्स के साथ-साथ प्रत्येक वर्ण करता है, और चार गलत प्रकार है, जो अधिकांश कंपाइलरों में 8 बिट बाइट्स होता है। यदि यह मल्टीबाइट है, तो हे, सभी दांव बंद हैं।

+1

नए बनाम malloc – bstpierre

+0

के लिए +1 मुझे नहीं पता कि मैं क्या कर रहा हूं सही है - लेकिन यह PQescapeStringConn - "'टू' के लिए दस्तावेज़ों से उत्पन्न होता है जो एक बफर को इंगित करेगा जो कम से कम एक और बाइट पकड़ने में सक्षम है लंबाई से दो गुना मूल्य " यहां से: http://www.postgresql.org/docs/7.3/static/libpq-exec.html – Gush

3

पहले कुछ शब्दावली:

  • पहला नमूना ढेर आवंटन कहा जाता है।
  • दूसरा नमूना स्टैक आवंटन कहा जाता है।

सामान्य नियम है:, ढेर पर आवंटित जब तक:

  1. सरणी के लिए आवश्यक आकार संकलन समय पर अज्ञात है।
  2. आवश्यक आकार कुल स्टैक आकार का 10% से अधिक है। विंडोज और लिनक्स पर डिफ़ॉल्ट स्टैक आकार आमतौर पर 1 या 2 एमबी होता है। तो आपकी स्थानीय सरणी 100,000 बाइट से अधिक नहीं होनी चाहिए।
+1

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

+1

@ मार्क एच: आप सही हैं कि 10% नियम मुख्य में आवंटित नहीं किया जाना चाहिए, और निश्चित रूप से पुनर्वित्त कोड में नहीं। हालांकि, मैं नहीं देखता कि गैर-शुद्ध कार्यों की तुलना में स्टैक ओवरफ़्लो के खिलाफ शुद्ध कार्य कितना सुरक्षित होगा। – StackedCrooked

+1

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

1

आपने सी ++ और सी दोनों के साथ अपना प्रश्न टैग किया है, लेकिन सी ++ में दूसरे समाधान की अनुमति नहीं है। परिवर्तनीय लंबाई सरणी केवल सी (99) में ही अनुमति दी जाती है।

यदि आपको लगता है कि 'लेन' स्थिर है, तो दोनों काम करेंगे।

malloc() (और सी ++ 'नया') ढेर पर स्मृति आवंटित करता है, जिसका अर्थ है कि आपको मुक्त() (या यदि आप 'नया', 'हटाएं') बफर, या स्मृति के साथ आवंटित करना है कभी पुनः दावा नहीं किया जाएगा (रिसाव)।

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

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

static char output[(len * 2) + 1]; 

इस के बाहर बफर की ओर इशारा वापस जाने के लिए सक्षम बनाता है:

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

आखिरकार, सी ++ में मॉलोक का उपयोग न करें जब तक कि आपके पास वास्तव में कोई अच्छा कारण नहीं है (यानी, realloc)। इसके बजाए 'नया' और साथ ही 'हटाएं' का प्रयोग करें।

+0

http: //gcc.gnu से।संगठन/onlinedocs/gcc/वैरिएबल-length.html आईएसओ सी 99 में परिवर्तनीय-लंबाई स्वचालित सरणी की अनुमति है, और विस्तार के रूप में जीसीसी उन्हें सी 0 9 मोड और सी ++ में स्वीकार करता है। मुझे लगता है कि यही कारण है कि यह जीसीसी का उपयोग करके मेरे लिए संकलित और काम करता है। मैं विश्वास कर सकता हूं कि यह सी ++ मानक या उस भाषा की उचित परिभाषा नहीं है जिसका आप उल्लेख कर सकते हैं। क्या मुझे सी ++ टैग हटा देना चाहिए? – Gush

+0

मैं केवल यह सोच रहा था कि आप किसका उपयोग कर रहे थे, लेकिन मेरे लिए सी ++ मानने के लिए, मैंने सोचा कि मैं आपको चेतावनी दूंगा कि वीएलए मानक सी ++ का हिस्सा नहीं है। –

+0

ठीक है। मुझे यह नहीं पता था और यह प्रासंगिक है – Gush

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