एलोका () का उपयोग अच्छा अभ्यास क्यों नहीं माना जाता है?


400

alloca()ढेर पर स्मृति को आवंटित करता है, न कि ढेर पर malloc()। इसलिए, जब मैं दिनचर्या से लौटता हूं तो स्मृति मुक्त हो जाती है। तो, वास्तव में यह गतिशील रूप से आवंटित स्मृति को मुक्त करने की मेरी समस्या को हल करता है। के माध्यम से आवंटित स्मृति को मुक्त करना malloc()एक प्रमुख सिरदर्द है और यदि किसी तरह याद किया जाता है तो सभी प्रकार की स्मृति समस्याओं का सामना करना पड़ता है।

alloca()उपरोक्त सुविधाओं के बावजूद हतोत्साहित का उपयोग क्यों किया जाता है?


40
बस एक त्वरित नोट। यद्यपि यह फ़ंक्शन अधिकांश संकलक में पाया जा सकता है, यह एएनएसआई-सी मानक द्वारा आवश्यक नहीं है और इसलिए पोर्टेबिलिटी को सीमित कर सकता है। एक और बात है, कि आपको नहीं करना चाहिए! फ्री () आपको मिलने वाला पॉइंटर और फंक्शन से बाहर निकलने के बाद यह अपने आप फ्री हो जाता है।
मर्कुरो

9
साथ ही, एलोका () के साथ एक फंक्शन इनलाइन के रूप में घोषित नहीं किया जाएगा।
जूलिक

2
@ जूलिकल, क्या आप कुछ स्पष्टीकरण दे सकते हैं? मैं बहुत उत्सुक हूं कि इस व्यवहार के पीछे क्या है
माइगेजेक

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

5
इसका एक और सकारात्मक पहलू allocaयह है कि ढेर ढेर की तरह खंडित नहीं हो सकता है। यह कठिन वास्तविक समय तक चलने वाली शैली के अनुप्रयोगों, या यहां तक ​​कि सुरक्षा महत्वपूर्ण अनुप्रयोगों के लिए उपयोगी साबित हो सकता है, क्योंकि WCRU तब समस्याओं के अपने स्वयं के सेट के साथ कस्टम मेमोरी पूल का सहारा लिए बिना सांख्यिकीय रूप से विश्लेषण किया जा सकता है (कोई अस्थायी इलाके नहीं, उप-इष्टतम संसाधन उपयोग)।
एंड्रियास

जवाबों:


245

उत्तर manपृष्ठ में वहीं है (कम से कम लिनक्स पर ):

RETURN VALUE एलोका () फ़ंक्शन आवंटित स्थान की शुरुआत के लिए एक संकेतक लौटाता है। यदि आवंटन स्टैक ओवरफ़्लो का कारण बनता है, तो प्रोग्राम व्यवहार अपरिभाषित है।

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


35
तो वहाँ वास्तव में इसके साथ कोई समस्या नहीं है कि आप भी बड़े सरणियों की घोषणा के साथ नहीं होगा?
TED

88
@ सीन: हां, स्टैक ओवरफ्लो जोखिम का कारण है, लेकिन वह कारण थोड़ा मूर्खतापूर्ण है। सबसे पहले क्योंकि (वैभव के अनुसार) बड़ी स्थानीय सरणियाँ ठीक उसी समस्या का कारण बनती हैं, लेकिन लगभग उतने नहीं होते हैं। इसके अलावा, पुनरावृत्ति बस स्टैक को आसानी से उड़ा सकती है। क्षमा करें, लेकिन मैं आपसे उम्मीद करता हूं कि प्रचलित विचार का मुकाबला करें कि मैन पेज में दिया गया कारण उचित है।
j_random_hacker

49
मेरा कहना यह है कि मैन पेज में दिए गए औचित्य का कोई मतलब नहीं है, क्योंकि अलोका () बिल्कुल उन चीजों (स्थानीय सरणियों या पुनरावर्ती कार्यों) के रूप में "बुरा" है, जिन्हें कोषेर माना जाता है।
j_random_hacker

39
@njjjj: अत्यधिक अनुभवी C / C ++ प्रोग्रामर द्वारा नहीं, लेकिन मुझे लगता है कि कई लोग जो डरते alloca()हैं, उन्हें स्थानीय सरणियों या पुनरावृत्ति का समान भय नहीं है (वास्तव में बहुत से लोग जो alloca()चिल्लाएंगे वे पुनरावृत्ति की प्रशंसा करेंगे क्योंकि "सुरुचिपूर्ण दिखता है") । मैं शॉन की सलाह से सहमत हूं ("एलोका (छोटे आवंटन के लिए ठीक है")) लेकिन मैं उस मानसिकता से असहमत हूं जो 3 के बीच अनोखा बुराई के रूप में फ्रेम करती है - वे समान रूप से खतरनाक हैं!
j_random_hacker

35
नोट: लिनक्स की "आशावादी" मेमोरी आवंटन रणनीति को देखते हुए, आपको बहुत संभावना है कि आपको ढेर-थकावट की विफलता का कोई संकेत नहीं मिलेगा ... इसके बजाय मॉलोक () आपको एक अच्छा गैर-पूर्ण सूचक लौटाएगा, और तब जब आप वास्तव में प्रयास करेंगे आपके द्वारा बताए गए पते के स्थान पर पहुँचें, आपकी प्रक्रिया (या कुछ अन्य प्रक्रिया, अप्रत्याशित रूप से) OOM- किलर द्वारा मारी जाएगी। बेशक, यह सी / सी + + प्रति मुद्दे के बजाय लिनक्स की एक "विशेषता" है, लेकिन यह ध्यान में रखते हुए कुछ है कि एलोका () या मॉलोक () "सुरक्षित" है या नहीं। :)
जेरेमी फ्रेज़र

209

सबसे यादगार कीड़े में से एक मैं एक इनलाइन फ़ंक्शन के साथ करना था जो उपयोग किया गया था alloca। यह कार्यक्रम के निष्पादन के यादृच्छिक बिंदुओं पर खुद को एक स्टैक ओवरफ्लो के रूप में प्रकट करता है (क्योंकि यह स्टैक पर आवंटित होता है)।

हेडर फ़ाइल में:

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

कार्यान्वयन फ़ाइल में:

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

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

तो सबक यह है - उन allocaकार्यों में उपयोग न करें जो आपको लगता है कि इनलाइन हो सकते हैं।


91
दिलचस्प। लेकिन यह एक संकलक बग के रूप में योग्य नहीं होगा? आखिरकार, इनलाइनिंग ने कोड के व्यवहार को बदल दिया (इसमें एलोका का उपयोग करके आवंटित स्थान को मुक्त करने में देरी हुई)।

60
जाहिरा तौर पर, कम से कम जीसीसी इसे ध्यान में रखेगा: "ध्यान दें कि एक फ़ंक्शन परिभाषा में कुछ उपयोग इसे इनलाइन प्रतिस्थापन के लिए अनुपयुक्त बना सकते हैं। इन usages में से हैं: varargs का उपयोग, alloca का उपयोग, [...]"। gcc.gnu.org/oniltocs/gcc/Inline.html
sleske

135
आप क्या संकलक धूम्रपान कर रहे थे?
थॉमस ईडिंग

22
मुझे समझ में नहीं आता है कि संकलक गुंजाइश का अच्छा उपयोग नहीं करता है यह निर्धारित करने के लिए कि उप-वर्ग में आवंटन कम या ज्यादा "मुक्त" हैं: स्टैक पॉइंटर गुंजाइश में प्रवेश करने से पहले अपने बिंदु पर वापस आ सकता है, जैसे कि क्या किया जाता है समारोह से लौट (यह नहीं कर सकता?)
मूला

7
मैंने अस्वीकार कर दिया है, लेकिन जवाब अच्छी तरह से लिखा है: मैं दूसरों के साथ सहमत हूं कि आप एक स्पष्ट रूप से संकलक बग क्या है के लिए आवंटित किया गया है । कंपाइलर ने एक अनुकूलन में दोषपूर्ण धारणा बनाई है जिसे इसे नहीं बनाना चाहिए था। कंपाइलर बग के आसपास काम करना ठीक है, लेकिन मैं इसके लिए कुछ भी नहीं करूंगा लेकिन कंपाइलर।
इवान कैरोल

75

पुराने प्रश्न लेकिन किसी ने उल्लेख नहीं किया कि इसे परिवर्तनशील लंबाई सरणियों द्वारा प्रतिस्थापित किया जाना चाहिए।

char arr[size];

के बजाय

char *arr=alloca(size);

यह मानक C99 में है और कई संकलक में संकलक विस्तार के रूप में मौजूद है।


5
यह आर्थर उल्फल्ड के जवाब के लिए एक टिप्पणी पर जोनाथन लेफ़लर द्वारा उल्लेख किया गया है।
निंजाल

2
वास्तव में, लेकिन यह भी दिखाता है कि यह कितना आसान है, क्योंकि पोस्टिंग से पहले सभी प्रतिक्रियाओं को पढ़ने के बावजूद मैंने इसे नहीं देखा था।
पैट्रिक श्ल्टर

6
एक नोट - वे परिवर्तनशील लंबाई सरणियाँ हैं, न कि गतिशील सरणियाँ। उत्तरार्द्ध resizable हैं और आमतौर पर ढेर पर लागू होते हैं।
टिम Timस

1
कुछ C ++ के विजुअल स्टूडियो 2015 में एक ही मुद्दा है।
आहॉक्स

2
लिनक्स कर्नेल में लीनस टॉर्वाल्ड्स वीएलए को पसंद नहीं करते हैं । संस्करण 4.20 के रूप में लिनक्स लगभग वीएलए मुक्त होना चाहिए।
बजे क्रिस्टियान सियुपिटु

60

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

आप काफी सुरक्षित हो सकते हैं यदि आप

  • पॉइंटर, या ऐसी किसी भी चीज़ को वापस न करें।
  • ढेर पर आवंटित किसी भी संरचना में सूचक को संग्रहीत न करें
  • किसी अन्य थ्रेड को पॉइंटर का उपयोग न करने दें

वास्तविक खतरा इस अवसर से आता है कि कोई और इन परिस्थितियों का उल्लंघन कुछ समय बाद करेगा। मन में यह है कि यह उन में पाठ स्वरूप प्रारूप कार्यों के लिए बफ़र पास करने के लिए बहुत अच्छा है :)


12
VLA (चर लंबाई सरणी) C99 की सुविधा गतिशील रूप से उपयोग किए जाने वाले आवोका () के बिना स्थानीय चर का समर्थन करती है।
जोनाथन लेफ़लर


1
लेकिन यह संकेत के साथ स्थानीय चर से निपटने से अलग नहीं है। उन्हें चारों ओर से भी बेवकूफ बनाया जा सकता है ...
ग्लोगल

2
@ जोनाथन लेफ़लर एक चीज़ जो आप एलोका के साथ कर सकते हैं लेकिन आप वीएलए के साथ नहीं कर सकते हैं उनके साथ प्रतिबंधित कीवर्ड का उपयोग कर रहे हैं। इस तरह: फ्लोट * हैवी_यूज्ड_रियर = एलोका (साइज़ोफ़ (फ्लोट) * साइज़) को प्रतिबंधित करें; फ्लोट के बजाय भारी_सुधार [आकार]। यह कुछ कंपाइलर (मेरे मामले में 4.8 gcc) को असेंबली को ऑप्टिमाइज़ करने में मदद कर सकता है, भले ही साइज़ एक कॉम्प्लेक्शन कॉन्स्टेंट हो। इसके बारे में मेरा प्रश्न देखें: stackoverflow.com/questions/19026643/use-restrict-with-arrays
Piotr Lopusiewicz

@JonathanLeffler A VLA उस ब्लॉक के लिए स्थानीय है जिसमें यह शामिल है। दूसरी ओर, alloca()फ़ंक्शन के अंत तक स्मृति को आवंटित करता है। इसका मतलब यह है कि वीएलए का सीधा, सुविधाजनक अनुवाद नहीं है f() { char *p; if (c) { /* compute x */ p = alloca(x); } else { p = 0; } /* use p */ }। यदि आपको लगता है कि allocaवीएलए के उपयोगों के उपयोग को स्वचालित रूप से अनुवाद करना संभव है, लेकिन इसका वर्णन करने के लिए एक टिप्पणी से अधिक की आवश्यकता है कि, मैं इसे कैसे एक प्रश्न बना सकता हूं।
पास्कल क्यूक

40

जैसा कि इस समाचार समूह की पोस्टिंग में बताया गया है , इसके कुछ कारण हैं जिनका उपयोग allocaकरना कठिन और खतरनाक माना जा सकता है:

  • सभी कंपाइलर सपोर्ट नहीं करते alloca
  • कुछ संकलक allocaअलग-अलग व्यवहार के अभिप्रेत व्यवहार की व्याख्या करते हैं , इसलिए संकलक के बीच पोर्टेबिलिटी की गारंटी नहीं है जो इसका समर्थन करते हैं।
  • कुछ कार्यान्वयन छोटी गाड़ी हैं।

24
एक बात जो मैंने उस लिंक पर उल्लिखित देखी, जो इस पृष्ठ पर कहीं नहीं है, वह यह है कि एक फ़ंक्शन जिसका उपयोग alloca()स्टैक पॉइंटर और फ़्रेम पॉइंटर को रखने के लिए अलग रजिस्टरों की आवश्यकता होती है। X86 सीपीयू> = 386 पर, स्टैक पॉइंटर ESPका उपयोग दोनों के लिए किया जा सकता है, मुक्त EBP- जब तक alloca()कि उपयोग नहीं किया जाता है।
13_30

10
उस पृष्ठ पर एक और अच्छी बात यह है कि जब तक संकलक का कोड जनरेटर इसे एक विशेष मामले के रूप में संभालता है, f(42, alloca(10), 43);इस संभावना के कारण दुर्घटनाग्रस्त हो सकता है कि स्टैक पॉइंटर को कम से कम एक तर्क के द्वारा उस पर धकेलने के alloca() बाद समायोजित किया जाता है।
j_random_hacker

3
जुड़ा हुआ पोस्ट जॉन लेविने द्वारा लिखा गया प्रतीत होता है- दोस्त जो "लिंकर्स और लोडर" लिखा था, मैं जो कुछ भी कहता हूं उस पर भरोसा करूंगा।
user318904

3
लिंक की गई पोस्ट जॉन लेविन की पोस्टिंग का जवाब है।
ए विलकॉक्स

6
याद रखिए, एक बहुत के बाद से 1991 के सभी आधुनिक सी compilers (2009 में भी) एक विशेष मामले के रूप alloca को संभालने के लिए है बदल गया है; यह एक सामान्य कार्य के बजाय एक आंतरिक है, और एक फ़ंक्शन को कॉल भी नहीं कर सकता है। तो, एलोका-इन-पैरामीटर मुद्दा (जो कि 1970 के दशक से के एंड आर सी में उत्पन्न हुआ था) अब एक समस्या नहीं होनी चाहिए। टोनी डी के जवाब पर किए गए एक टिप्पणी में अधिक विस्तार से
17'17

26

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


21

अभी भी आवंटित उपयोग को हतोत्साहित किया जाता है, क्यों?

मैं इस तरह की आम सहमति का अनुभव नहीं करता हूं। मजबूत पेशेवरों के बहुत सारे; कुछ बुरा:

  • C99 परिवर्तनीय लंबाई सरणियाँ प्रदान करता है, जिसका उपयोग अक्सर अधिमान्य रूप से किया जाता है क्योंकि निश्चित लंबाई सरणियों और सहज समग्र के साथ संकेतन अधिक सुसंगत है।
  • कई प्रणालियों में ढेर के लिए स्टैक के लिए कम समग्र मेमोरी / एड्रेस-स्पेस उपलब्ध है, जो प्रोग्राम को मेमोरी थकावट (स्टैक ओवरफ्लो के माध्यम से) के लिए अतिसंवेदनशील बनाता है: इसे एक अच्छी या बुरी चीज के रूप में देखा जा सकता है - एक स्टैक स्वचालित रूप से बढ़ने का कारण नहीं बनता है, जिससे पूरे प्रोग्राम पर आउट-ऑफ-कंट्रोल प्रोग्रामों को अधिक प्रतिकूल प्रभाव होने से रोका जा सकता है।
  • जब एक और अधिक स्थानीय गुंजाइश (जैसे कि एक के रूप में में इस्तेमाल किया whileया forपाश) या कई कार्यक्षेत्रों में, स्मृति यात्रा प्रति / गुंजाइश जम जाता है और समारोह रास्ते तक जारी नहीं किया गया है: एक नियंत्रण संरचना के दायरे में परिभाषित सामान्य चर के साथ इस विरोधाभासों (जैसे एक्स पर अनुरोधित मेमोरी for {int i = 0; i < 2; ++i) { X }को संचित allocaकिया जाएगा , लेकिन एक निश्चित आकार के सरणी के लिए मेमोरी को पुनरावृत्ति प्रति पुनर्नवीनीकरण किया जाएगा)।
  • आधुनिक कंपाइलर आमतौर पर inlineकॉल करने वाले फ़ंक्शन नहीं करते हैं alloca, लेकिन यदि आप उन्हें मजबूर करते हैं तो allocaकॉलर्स के संदर्भ में होगा (यानी कॉलर के वापस आने तक स्टैक जारी नहीं किया जाएगा)
  • बहुत समय पहले allocaएक गैर-पोर्टेबल सुविधा / हैक से एक मानकीकृत एक्सटेंशन में संक्रमण हुआ था , लेकिन कुछ नकारात्मक धारणा बनी रह सकती है
  • जीवनकाल फ़ंक्शन स्कोप के लिए बाध्य है, जो प्रोग्रामर के mallocस्पष्ट नियंत्रण से बेहतर नहीं हो सकता है या नहीं
  • उपयोग करने के लिए mallocप्रोत्साहित करने के बारे में सोच के बारे में सोच - यदि वह एक आवरण समारोह (जैसे WonderfulObject_DestructorFree(ptr)) के माध्यम से प्रबंधित किया जाता है , तो फ़ंक्शन क्लाइंट को स्पष्ट परिवर्तनों के बिना कार्यान्वयन क्लीन अप ऑपरेशंस (जैसे फाइल डिस्क्रिप्टर को बंद करना, आंतरिक बिंदुओं को मुक्त करना या कुछ लॉगिंग करना) के लिए एक बिंदु प्रदान करता है। कोड: कभी-कभी यह लगातार अपनाने के लिए एक अच्छा मॉडल है
    • प्रोग्रामिंग के इस छद्म-ऊ की शैली में, कुछ ऐसा चाहना स्वाभाविक है WonderfulObject* p = WonderfulObject_AllocConstructor();- ऐसा तब संभव है जब "कंस्ट्रक्टर" एक फ़ंक्शन रिटर्निंग mallocमेमोरी हो (जैसा कि फ़ंक्शन द्वारा संग्रहित किए जाने वाले मान को वापस करने के बाद मेमोरी आवंटित रहती है p), लेकिन नहीं अगर "कंस्ट्रक्टर" उपयोग करता हैalloca
      • एक स्थूल संस्करण WonderfulObject_AllocConstructorइसे हासिल कर सकता है, लेकिन "मैक्रोज़ बुराई हैं" इसमें वे एक-दूसरे और गैर-मैक्रो कोड के साथ संघर्ष कर सकते हैं और अनपेक्षित प्रतिस्थापन और परिणामस्वरूप कठिन-से-निदान समस्याएं पैदा कर सकते हैं
    • लापता freeसंचालन का पता वालग्रिंड, शुद्ध आदि द्वारा लगाया जा सकता है, लेकिन लापता "विध्वंसक" कॉल का हमेशा पता नहीं लगाया जा सकता है - इच्छित उपयोग के प्रवर्तन के संदर्भ में एक बहुत ही कठिन लाभ; कुछ alloca()कार्यान्वयन (जैसे GCC के) के लिए एक इनलाइन मैक्रो का उपयोग करते हैं alloca(), इसलिए मेमोरी-यूज़ डायग्नोस्टिक लाइब्रेरी का रनटाइम प्रतिस्थापन उस तरह से संभव नहीं है जैसे malloc/ realloc/ free(जैसे इलेक्ट्रिक बाड़)
  • कुछ कार्यान्वयन में सूक्ष्म मुद्दे हैं: उदाहरण के लिए, लिनक्स मैनपेज से:

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


मुझे पता है कि इस सवाल को C टैग किया गया है, लेकिन C ++ प्रोग्रामर के रूप में मुझे लगा कि मैं संभावित उपयोगिता बताने के लिए C ++ का उपयोग करूंगा alloca: नीचे दिए गए कोड (और यहां ideone पर ) एक वेक्टर ट्रैकिंग को अलग-अलग आकार के पॉलीमोर्फिक प्रकार बनाता है जो आवंटित किया जाता है (के साथ) आवंटित किए गए ढेर के बजाए जीवन भर काम के बदले)।

#include <alloca.h>
#include <iostream>
#include <vector>

struct Base
{
    virtual ~Base() { }
    virtual int to_int() const = 0;
};

struct Integer : Base
{
    Integer(int n) : n_(n) { }
    int to_int() const { return n_; }
    int n_;
};

struct Double : Base
{
    Double(double n) : n_(n) { }
    int to_int() const { return -n_; }
    double n_;
};

inline Base* factory(double d) __attribute__((always_inline));

inline Base* factory(double d)
{
    if ((double)(int)d != d)
        return new (alloca(sizeof(Double))) Double(d);
    else
        return new (alloca(sizeof(Integer))) Integer(d);
}

int main()
{
    std::vector<Base*> numbers;
    numbers.push_back(factory(29.3));
    numbers.push_back(factory(29));
    numbers.push_back(factory(7.1));
    numbers.push_back(factory(2));
    numbers.push_back(factory(231.0));
    for (std::vector<Base*>::const_iterator i = numbers.begin();
         i != numbers.end(); ++i)
    {
        std::cout << *i << ' ' << (*i)->to_int() << '\n';
        (*i)->~Base();   // optionally / else Undefined Behaviour iff the
                         // program depends on side effects of destructor
    }
}

कई प्रकारों को संभालने के
फिजूलखर्ची के

@einpoklum: अच्छी तरह से यह गहन ज्ञानवर्धक है ... धन्यवाद।
टोनी डेलारॉय

1
मुझे rephrase दें: यह एक बहुत अच्छा जवाब है। उस बिंदु तक जहां मुझे लगता है कि आप सुझाव दे रहे हैं कि लोग एक प्रकार के प्रति-पैटर्न का उपयोग करते हैं।
einpoklum

लिनक्स मैनपेज की टिप्पणी बहुत पुरानी है और, मुझे पूरा यकीन है, अप्रचलित है। सभी आधुनिक संकलक जानते हैं कि एलोका () क्या है, और इस तरह से अपने फावड़े पर यात्रा नहीं करेंगे। पुराने K & R C में, (1) सभी फ़ंक्शन फ़्रेम पॉइंटर्स (2) का उपयोग करते थे, सभी फ़ंक्शन कॉल {स्टैक पर पुश पुश} {कॉल फ़ंक} {ऐड # एन, स्प} होते थे। एलोका एक ऐसा कार्य था जो बस स्टैक को टक्कर देगा, संकलक को भी इस बारे में पता नहीं था। (1) और (2) सच नहीं हैं, इसलिए एलाका उस तरह से काम नहीं कर सकता (अब यह एक आंतरिक है)। पुरानी सी में, धक्का देने वाले आर्गों के बीच में एलोका को कॉल करना स्पष्ट रूप से उन मान्यताओं को भी तोड़ देगा।
ग्रेगोगो

4
उदाहरण के बारे में, मैं आम तौर पर ऐसी किसी चीज़ के बारे में चिंतित होता हूँ जिसे स्मृति भ्रष्टाचार से बचने के लिए हमेशा_इनलाइन की आवश्यकता होती है ....
greggo

14

अन्य सभी उत्तर सही हैं। हालाँकि, यदि आप जिस चीज़ का उपयोग कर आवंटित करना चाहते हैं alloca(), वह काफी छोटी है, तो मुझे लगता है कि यह एक अच्छी तकनीक है जो उपयोग करने की तुलना में तेज़ और अधिक सुविधाजनक है malloc()या अन्यथा।

दूसरे शब्दों में, alloca( 0x00ffffff )खतरनाक है और अतिप्रवाह पैदा करने की संभावना है, बिल्कुल उतना ही char hugeArray[ 0x00ffffff ];। सतर्क और उचित रहें और आप ठीक रहेंगे।


12

इस "पुराने" सवाल के कई दिलचस्प जवाब, यहां तक ​​कि कुछ अपेक्षाकृत नए जवाब भी, लेकिन मुझे ऐसा कोई भी नहीं मिला जो इस बात का उल्लेख करता हो ...।

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

मुझे वह बोली .... ठीक है, मैंने वह बोली। लेकिन वास्तव में, इसके बारे में सोचो ...।

अन्य उत्तरों के तहत उनकी टिप्पणियों में @j_random_hacker बहुत सही है: alloca()ओवरसाइज़्ड स्थानीय सरणियों के पक्ष में उपयोग से बचने से आपका प्रोग्राम स्टैक ओवरफ्लो से सुरक्षित नहीं हो जाता है (जब तक कि आपका कंपाइलर पुराने कार्य करने की अनुमति देने के लिए पर्याप्त नहीं है alloca()जो उस स्थिति में आपको उपयोग करना चाहिए अपग्रेड करें, या जब तक आप alloca()लूप के अंदर का उपयोग नहीं करते हैं , जिस स्थिति में आपको ... alloca()लूप के अंदर का उपयोग नहीं करना चाहिए )।

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

alloca() (या वीएलएएस) नौकरी के लिए सिर्फ सही उपकरण हो सकता है।

मैंने समय और समय फिर से देखा है जहां एक प्रोग्रामर स्टैक-आवंटित बफर बनाता है "किसी भी संभावित मामले को संभालने के लिए पर्याप्त बड़ा"। एक गहरी नेस्टेड कॉल ट्री में, उस (एंटी?) पैटर्न के बार-बार उपयोग से अतिरंजित स्टैक का उपयोग होता है। (एक कॉल ट्री की कल्पना करें 20 लेवल गहरे, जहाँ हर स्तर पर अलग-अलग कारणों से, फंक्शन आँख बंद करके 1024 बाइट्स के एक बफ़र को "बस सुरक्षित रहने के लिए" आवंटित करता है) जब आम तौर पर यह केवल 16 या उससे कम का उपयोग करेगा, और केवल बहुत में दुर्लभ मामले अधिक उपयोग कर सकते हैं।) एक विकल्प का उपयोग करना हैalloca()या VLAs और अनावश्यक रूप से स्टैक को टालने से बचने के लिए आपके फ़ंक्शन की ज़रूरत के अनुसार केवल अधिक स्टैक स्थान आवंटित करें। उम्मीद है कि जब कॉल ट्री में एक फ़ंक्शन को बड़े-से-सामान्य आवंटन की आवश्यकता होती है, तो कॉल ट्री के अन्य लोग अभी भी अपने सामान्य छोटे आवंटन का उपयोग कर रहे हैं, और समग्र अनुप्रयोग स्टैक उपयोग की तुलना में काफी कम है यदि प्रत्येक फ़ंक्शन नेत्रहीन एक स्थानीय बफर को आवंटित करता है ।

लेकिन अगर आप उपयोग करना चुनते हैं alloca()...

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


मैं इस बात से सहमत हूं। के खतरनाक alloca()सच है, लेकिन वही कहा जा सकता है के साथ स्मृति लीकmalloc() (क्यों एक GC का उपयोग नहीं करते? तो एक बहस हो सकती है)। alloca()जब देखभाल के साथ प्रयोग किया जाता है तो स्टैक आकार को कम करने के लिए वास्तव में उपयोगी हो सकता है।
फेलिप टोनेलो

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

सिडेनोट: "एक निश्चित बफर [MAX_SIZE] का उपयोग करके" उदाहरण पर प्रकाश डाला गया है कि स्मृति नीति इतनी अच्छी तरह से क्यों काम करती है। कार्यक्रम स्मृति को आवंटित करते हैं वे कभी भी अपनी बफर लंबाई की सीमा को छोड़कर नहीं छू सकते हैं। तो यह ठीक है कि लिनक्स (और अन्य ओएस के) वास्तव में मेमोरी के एक पेज को तब तक असाइन नहीं करते हैं जब तक कि इसका पहला उपयोग नहीं किया जाता है (जैसा कि मॉलॉक के विपरीत)। यदि बफ़र एक पृष्ठ से बड़ा है, तो प्रोग्राम केवल पहले पृष्ठ का उपयोग कर सकता है, और शेष भौतिक मेमोरी को बर्बाद नहीं करेगा।
कटस्टिक यात्रा

@KatasticVoyage जब तक MAX_SIZE आपके सिस्टम के वर्चुअल मेमोरी पेज के आकार से अधिक (या कम से कम बराबर), आपके तर्क में पानी नहीं है। वर्चुअल मेमोरी के बिना एम्बेडेड सिस्टम पर (कई एम्बेडेड MCU की MMU नहीं है), ओवरकमिटी मेमोरी पॉलिसी "आपके प्रोग्राम को सभी स्थितियों में चलेगी सुनिश्चित करें" से अच्छा हो सकता है, लेकिन यह आश्वासन उस कीमत के साथ आता है जो आपके स्टैक के आकार की है इसी तरह स्मृति नीति का समर्थन करने के लिए आवंटित किया जाना चाहिए। कुछ एम्बेडेड सिस्टम पर, यह एक कीमत है कि कम लागत वाले उत्पादों के कुछ निर्माता भुगतान करने के लिए तैयार नहीं हैं।
फोनेटैगर

11

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

आप इस SEH अपवाद को पकड़ सकते हैं और स्टैक को रीसेट करने के लिए _resetstkoflw को कॉल कर सकते हैं और अपने मीरा रास्ते पर जारी रख सकते हैं। आदर्श नहीं है, लेकिन यह कम से कम कुछ पता करने के लिए एक और तंत्र है जब सामान पंखे से टकरा जाता है। * निक्स में कुछ ऐसा ही हो सकता है, जिसकी मुझे जानकारी नहीं है।

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

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


समस्या यह है, कि alloca()ढेर जगह की मांग कर सकते हैं, ढेर ढेर भूमि। इसके साथ, एक हमलावर जो alloca()उस बफर में जाने वाले डेटा के लिए आकार को नियंत्रित कर सकता है और ढेर को मिटा सकता है (जो बहुत बुरा है)।
12431234123412341234123

SEH एक Windows- केवल एक चीज है। यह बहुत अच्छा है यदि आप केवल Windows पर चलने वाले अपने कोड की परवाह करते हैं, लेकिन यदि आपके कोड को क्रॉस-प्लेटफ़ॉर्म करने की आवश्यकता है (या यदि आप ऐसा कोड लिख रहे हैं जो केवल गैर-विंडोज प्लेटफ़ॉर्म पर चलता है), तो आप होने पर भरोसा नहीं कर सकते SEH।
जॉर्ज

10

alloca () अच्छा और कुशल है ... लेकिन यह भी गहरा टूटा हुआ है।

  • टूट गुंजाइश व्यवहार (ब्लॉक गुंजाइश के बजाय फ़ंक्शन गुंजाइश)
  • मॉलोक के साथ असंगत का उपयोग करें ( एलोका () युक्त सूचक को मुक्त नहीं किया जाना चाहिए, इसलिए आपको यह ट्रैक करना होगा कि आप पॉइंटर्स कहाँ से आ रहे हैं मुफ्त () केवल जिन्हें आपने मॉलॉक () के साथ मिला है )
  • बुरा व्यवहार जब आप भी इनलाइनिंग का उपयोग करते हैं (गुंजाइश कभी-कभी कॉलर फ़ंक्शन पर निर्भर करती है कि कैली इनलाइन है या नहीं)।
  • कोई स्टैक सीमा जाँच नहीं
  • विफलता के मामले में अपरिभाषित व्यवहार (मॉलॉक की तरह पूर्ण नहीं लौटाता है ... और विफलता का क्या मतलब है क्योंकि यह स्टैक सीमाओं की जांच नहीं करता है ...)
  • एएनएसआई मानक नहीं

ज्यादातर मामलों में आप इसे स्थानीय चर और प्रमुख आकार का उपयोग करके बदल सकते हैं। यदि यह बड़ी वस्तुओं के लिए उपयोग किया जाता है, तो उन्हें ढेर पर रखना आमतौर पर एक सुरक्षित विचार है।

यदि आपको वास्तव में सी की जरूरत है तो आप वीएलए (सी ++ में कोई वीएलए, बहुत खराब) का उपयोग कर सकते हैं। वे गुंजाइश व्यवहार और स्थिरता के बारे में एलोका () से बहुत बेहतर हैं। मैं इसे देख VLA का एक प्रकार है alloca () सही बनाया है।

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


मैं नीचे (बिना किसी टिप्पणी के) कारण नहीं देखता
gd1

केवल नामों की गुंजाइश है। allocaएक नाम नहीं बनाता है, केवल एक मेमोरी रेंज है, जिसमें जीवनकाल है
जिज्ञासु

@ कुरसी: आप केवल शब्दों के साथ खेल रहे हैं। स्वचालित चर के लिए मैं अंतर्निहित मेमोरी के जीवनकाल के बारे में बात कर सकता हूं क्योंकि यह नाम के दायरे से मेल खाता है। वैसे भी परेशानी यह नहीं है कि हम इसे कैसे कहते हैं, लेकिन जीवन भर की अस्थिरता / स्मृति का दायरा एलाका और असाधारण व्यवहार से वापस आ गया।
क्रिश

2
मेरी इच्छा है कि एलोका के पास एक समान "फ़्रीआ" था, एक विनिर्देशन के साथ जो "फ़्रीआ" कहकर "एलोका" के प्रभाव को पैदा करेगा, जो ऑब्जेक्ट और सभी बाद वाले लोगों को बनाएगा, और एक आवश्यकता है कि स्टोरेज के भीतर 'ऑलोकैड' का भंडारण करना होगा उसके भीतर भी 'फ़्री'एड होना। यह एक सुसंगत फैशन में alloca / freea का समर्थन करने के लिए लगभग सभी कार्यान्वयन के लिए संभव बना दिया है, inlining मुद्दों को कम किया होगा, और आम तौर पर चीजों को एक बहुत क्लीनर बनाया।
सुपरकाट

2
@ सुपरकैट - काश ऐसा भी होता। यही कारण है कि (और अधिक) के लिए, मैं एक अमूर्त परत (ज्यादातर मैक्रो और इनलाइन कार्यों) ताकि मैं कभी भी कॉल नहीं करते उपयोग करें allocaया mallocया freeसीधे। मैं चीजों की तरह कहते हैं {stack|heap}_alloc_{bytes,items,struct,varstruct}और {stack|heap}_dealloc। तो, heap_deallocसिर्फ कॉल freeऔर stack_deallocएक नो-ऑप है। इस तरह, ढेर आवंटन आसानी से आवंटन को कम करने के लिए डाउनग्रेड किया जा सकता है, और इरादे भी अधिक स्पष्ट हैं।
टॉड लेहमन

9

यहाँ पर क्यों:

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

ऐसा नहीं है कि कोई भी इस कोड को लिखेगा, लेकिन जिस आकार के तर्क को आप allocaलगभग निश्चित रूप से पास कर रहे हैं, वह किसी प्रकार के इनपुट से आता है, जो आपके प्रोग्राम को पाने के लिए दुर्भावनापूर्ण तरीके से लक्ष्य कर सकता है।alloca कुछ इस तरह विशाल है। आखिरकार, यदि आकार इनपुट पर आधारित नहीं है या आपके बड़े होने की संभावना नहीं है, तो आपने केवल एक छोटे, निश्चित आकार के विशाल बफर की घोषणा क्यों नहीं की?

वस्तुतः सभी कोड का उपयोग allocaऔर / या C99 vlas में गंभीर कीड़े हैं जो क्रैश (यदि आप भाग्यशाली हैं) या विशेषाधिकार समझौता करेंगे (यदि आप इतने भाग्यशाली नहीं हैं)।


1
दुनिया को कभी पता नहीं हो सकता। :( यह कहा, मुझे उम्मीद है कि आप मेरे बारे में एक प्रश्न स्पष्ट कर सकते हैं alloca। आपने कहा कि इसका उपयोग करने वाले लगभग सभी कोड में एक बग है, लेकिन मैं इसका उपयोग करने की योजना बना रहा था; मैं आमतौर पर इस तरह के दावे को अनदेखा करता हूं, लेकिन आ रहा है आप से मैं नहीं करूँगा। मैं एक वर्चुअल मशीन लिख रहा हूँ और मैं ऐसे वेरिएबल को आबंटित करना चाहता हूँ, जो डायनेमिक रूप से, भारी गति के कारण स्टैक पर होने वाले फंक्शन से नहीं बचते हैं। क्या इसका कोई विकल्प है। दृष्टिकोण जिसमें समान प्रदर्शन विशेषताएं हैं! मैं जानता हूं कि मैं मेमोरी पूल के साथ करीब हो सकता हूं, लेकिन यह अभी भी उतना सस्ता नहीं है। आप क्या करेंगे?
GManNickG

7
जानिए क्या है खतरनाक? यह: *0 = 9;अद्भुत !!! मुझे लगता है कि मुझे कभी भी पॉइंटर्स का उपयोग नहीं करना चाहिए (या कम से कम उन्हें डिफरेंस करना चाहिए)। इरेट, वेट। मैं यह देखने के लिए परीक्षण कर सकता हूं कि क्या यह अशक्त है। हम्म। मुझे लगता है कि मैं उस मेमोरी के आकार का भी परीक्षण कर सकता हूं जिसे मैं आवंटित करना चाहता हूं alloca। अजीब आदमी है। अजीब।
थॉमस एडिंग

7
*0=9;क्या मान्य नहीं है। जिस आकार को आप पास करते हैं alloca, उसका परीक्षण करने के लिए , इसका परीक्षण किसके खिलाफ करें? सीमा जानने का कोई तरीका नहीं है, और यदि आप इसे एक छोटे से ज्ञात ज्ञात सुरक्षित आकार (जैसे 8k) के खिलाफ परीक्षण करने जा रहे हैं, तो आप बस स्टैक पर एक निश्चित आकार के सरणी का उपयोग कर सकते हैं।
आर .. गिटहब स्टॉप हेल्पिंग ICE

7
आपके "या तो आकार के साथ परेशानी काफी छोटी जानी जाती है या यह इनपुट-निर्भर है और इस तरह मनमाने ढंग से बड़ी हो सकती है" जैसा कि मैं देख रहा हूं यह है कि यह केवल पुनरावृत्ति के लिए दृढ़ता से लागू होता है। एक व्यावहारिक समझौता (दोनों मामलों के लिए) यह मान लेना है कि यदि आकार से बंधा हुआ है, small_constant * log(user_input)तो हमारे पास पर्याप्त मेमोरी है।
j_random_hacker 3

1
वास्तव में, आपने एक मामले की पहचान की है जहां वीएलए / एलोका उपयोगी है: पुनरावर्ती एल्गोरिदम जहां किसी भी कॉल फ्रेम में अधिकतम स्थान की आवश्यकता एन के रूप में बड़ी हो सकती है, लेकिन जहां सभी पुनरावृत्ति स्तरों पर आवश्यक स्थान का योग एन या कुछ फ़ंक्शन है एन का कि जल्दी से नहीं बढ़ता है।
R .. गिटहब स्टॉप हेल्पिंग ICE

9

मुझे नहीं लगता कि किसी ने इसका उल्लेख किया है: किसी फ़ंक्शन में एलोका का उपयोग कुछ अनुकूलन को बाधित या अक्षम करेगा जो फ़ंक्शन में अन्यथा लागू किया जा सकता है, क्योंकि कंपाइलर फ़ंक्शन के स्टैक फ्रेम के आकार को नहीं जान सकता है।

उदाहरण के लिए, सी कंपाइलर्स द्वारा एक सामान्य अनुकूलन एक फ़ंक्शन के भीतर फ्रेम पॉइंटर के उपयोग को समाप्त करना है, इसके बजाय स्टैक पॉइंटर के सापेक्ष फ्रेम एक्सेस किए जाते हैं; इसलिए सामान्य उपयोग के लिए एक और रजिस्टर है। लेकिन अगर अलोका को फ़ंक्शन के भीतर बुलाया जाता है, तो sp और fp के बीच का अंतर फ़ंक्शन के भाग के लिए अज्ञात होगा, इसलिए यह अनुकूलन नहीं किया जा सकता है।

इसके उपयोग की दुर्लभता, और एक मानक कार्य के रूप में इसकी छायादार स्थिति को देखते हुए, कंपाइलर डिज़ाइनर संभवतः किसी भी अनुकूलन को अक्षम कर देते हैं जो कि एलोका के साथ परेशानी का कारण बन सकता है, अगर यह एलोका के साथ काम करने के लिए थोड़ा अधिक प्रयास करेगा।

अद्यतन: चूंकि चर-लंबाई वाले स्थानीय सरणियों को C में जोड़ा गया है, और चूंकि ये सभी समान-कोड वाले मुद्दों को संकलक के रूप में प्रस्तुत करते हैं, इसलिए मैं देखता हूं कि 'उपयोग की दुर्लभता और छायादार स्थिति' अंतर्निहित तंत्र पर लागू नहीं होती है; लेकिन मुझे अभी भी संदेह होगा कि एलोका या वीएलए का उपयोग किसी फ़ंक्शन के भीतर कोड पीढ़ी से समझौता करने के लिए जाता है जो उनका उपयोग करता है। मैं कंपाइलर डिजाइनरों से किसी भी प्रतिक्रिया का स्वागत करूंगा।


1
परिवर्तनीय लंबाई सरणियों को C ++ में कभी नहीं जोड़ा गया।
निर फ्रीडमैन

@NirFriedman वास्तव में। मुझे लगता है कि एक विकिपीडिया सुविधा सूची थी जो एक पुराने प्रस्ताव पर आधारित थी।
ग्रोग्गो

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

8

के साथ allocaएक longjmpनुकसान यह है कि यह याद दिलाता है।

यह कहना है, यदि आप किसी संदर्भ को सहेजते हैं setjmp, तो allocaकुछ स्मृति को, फिर longjmpसंदर्भ को, आप allocaस्मृति को खो सकते हैं । स्टैक पॉइंटर वापस आ गया है जहां यह था और इसलिए मेमोरी अब आरक्षित नहीं है; यदि आप किसी फ़ंक्शन को कॉल करते हैं या किसी अन्य को करते हैं alloca, तो आप मूल को बंद कर देंगे alloca

स्पष्ट करने के लिए, जो मैं विशेष रूप से यहां उल्लेख कर रहा हूं वह एक ऐसी स्थिति है, जिसमें longjmpफ़ंक्शन से बाहर नहीं लौटा है जहां allocaजगह ले ली गई है! बल्कि, एक फ़ंक्शन संदर्भ को बचाता है setjmp; इसके बाद मेमोरी को आवंटित किया जाता है allocaऔर अंत में एक longjmp उस संदर्भ में जगह लेता है। उस फ़ंक्शन की allocaमेमोरी को सभी मुक्त नहीं किया गया है; बस सभी मेमोरी जो इसे आवंटित की गई है setjmp। बेशक, मैं एक मनाया व्यवहार के बारे में बोल रहा हूं; ऐसी किसी भी आवश्यकता का दस्तावेज नहीं हैalloca जो मुझे पता हो।

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

संयोग से, यह, अगर यह उस तरह से काम करता है, तो जानबूझकर मुक्त स्मृति के लिए एक प्रशंसनीय तंत्र प्रदान करता है जिसे इसके साथ आवंटित किया गया था alloca

मैं इसे बग के मूल कारण के रूप में चलाता हूं।


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

1
man allocaनिम्नलिखित वाक्य दिया: "क्योंकि अलोका () द्वारा आवंटित स्थान को स्टैक फ्रेम के भीतर आवंटित किया गया है, उस स्थान को स्वचालित रूप से मुक्त किया जाता है यदि फ़ंक्शन रिटर्न को लॉन्गजम्प (3) या सिग्लिग्जम्प (3) के लिए कॉल द्वारा जंप किया जाता है।" तो यह प्रलेखित है कि स्मृति के साथ आवंटित allocaएक के बाद बंद हो जाता है longjmp
तहफ्फ

@tehftw वर्णित स्थिति बिना किसी फ़ंक्शन रिटर्न द्वारा कूदने पर होती है longjmp। लक्ष्य समारोह अभी तक वापस नहीं आया है। यह किया है setjmp, allocaऔर फिर longjmplongjmpरिवाइंड कर सकते हैं allocaक्या यह पर था करने के लिए राज्य वापस setjmpसमय। यह कहना है, allocaएक स्थानीय चर के रूप में एक ही समस्या से ग्रस्त पॉइंटर को चिह्नित नहीं किया गया है volatile!
कज़

3
मुझे समझ नहीं आता कि यह अप्रत्याशित क्यों माना जाएगा। जब आप setjmpतब alloca, और फिर longjmp, यह सामान्य है कि allocaउल्टा हो जाएगा। पूरे बिंदु longjmpको उस स्थिति में वापस जाना है जिसे बचाया गया था setjmp!
तेहफ्थ

@tehftw मैंने इस विशेष इंटरैक्शन को कभी भी प्रलेखित नहीं देखा है। इसलिए, यह संकलक के साथ अनुभवजन्य जांच के अलावा, किसी भी तरह से भरोसा नहीं किया जा सकता है।
कज़

7

एक जगह जहां alloca()विशेष रूप से खतरनाक malloc()है कर्नेल - एक ठेठ ऑपरेटिंग सिस्टम के कर्नेल में एक निश्चित आकार का स्टैक स्पेस होता है, जो इसके हेडर में हार्ड-कोडित होता है; यह एक आवेदन के ढेर के रूप में लचीला नहीं है। alloca()अनजान आकार के साथ कॉल करने से कर्नेल क्रैश हो सकता है। कुछ संकलक alloca()कर्नेल कोड संकलित करते समय चालू किए जाने वाले कुछ विकल्पों के तहत (और यहां तक ​​कि उस मामले के लिए भी वीएलए) के उपयोग की चेतावनी देते हैं - यहाँ, यह ढेर में मेमोरी आवंटित करना बेहतर है जो एक हार्ड-कोड सीमा द्वारा तय नहीं है।


7
alloca()से अधिक नहीं खतरनाक है int foo[bar];जहां barकुछ मनमाने ढंग से पूर्णांक है।
टोड लेहमैन

@ToddLehman यह सही है, और उस सटीक कारण के लिए हमने कर्ल में कई वर्षों के लिए वीएलए पर प्रतिबंध लगा दिया है, और 2018 के बाद से वीएलए मुक्त हो गया है :-)
क्रिस डाउन

6

यदि आप गलती से आवंटित ब्लॉक से परे लिखते हैं alloca(उदाहरण के लिए एक बफर अतिप्रवाह के कारण), तो आप अपने फ़ंक्शन के रिटर्न एड्रेस को ओवरराइट कर देंगे , क्योंकि यह स्टैक पर "ऊपर" स्थित है, अर्थात आपके आवंटित ब्लॉक के बाद

स्टैक पर _लोका ब्लॉक

इसका परिणाम दो गुना है:

  1. कार्यक्रम शानदार ढंग से दुर्घटनाग्रस्त हो जाएगा और यह बताना असंभव होगा कि यह क्यों या कहाँ दुर्घटनाग्रस्त हो गया (ढेर अधिलेखित फ्रेम पॉइंटर के कारण यादृच्छिक पते पर सबसे अधिक खोल देगा)।

  2. यह बफर को कई गुना अधिक खतरनाक बना देता है, क्योंकि एक दुर्भावनापूर्ण उपयोगकर्ता एक विशेष पेलोड को तैयार कर सकता है जिसे स्टैक पर रखा जाएगा और इसलिए इसे निष्पादित किया जा सकता है।

इसके विपरीत, यदि आप ढेर पर एक ब्लॉक से आगे लिखते हैं तो आप "बस" ढेर भ्रष्टाचार प्राप्त करते हैं। कार्यक्रम शायद अप्रत्याशित रूप से समाप्त हो जाएगा, लेकिन स्टैक को ठीक से खोल देगा, जिससे दुर्भावनापूर्ण कोड निष्पादन की संभावना कम हो जाएगी।


11
इस स्थिति में कुछ भी नाटकीय रूप से एक निश्चित आकार के ढेर-आवंटित बफर के अतिप्रवाहित बफर के खतरों से अलग नहीं है। यह खतरा अद्वितीय नहीं है alloca
फोनेटेगर

2
बिलकूल नही। लेकिन कृपया मूल प्रश्न की जाँच करें। सवाल यह है: क्या खतरे की allocaतुलना में है malloc(इस प्रकार स्टैक पर निश्चित आकार के बफर नहीं)।
रस्टीक्स

मामूली बिंदु, लेकिन कुछ प्रणालियों पर ढेर ऊपर की ओर बढ़ते हैं (जैसे PIC 16-बिट माइक्रोप्रोसेसर)।
इबलेक

5

अफसोस की बात है कि वास्तव में भयानक alloca()लगभग भयानक tcc से गायब है। Gcc है alloca()

  1. यह अपने विनाश का बीज बोता है। संहारक के रूप में वापसी के साथ।

  2. जैसे malloc()कि यह विफल होने पर एक अमान्य पॉइंटर देता है जो आधुनिक सिस्टम पर MMU के साथ सेगफ़ॉल्ट करेगा (और उम्मीद है कि बिना उन लोगों को पुनरारंभ करें)।

  3. ऑटो चर के विपरीत आप रन समय पर आकार निर्दिष्ट कर सकते हैं।

यह पुनरावृत्ति के साथ अच्छी तरह से काम करता है। आप पूंछ पुनरावृत्ति के समान कुछ हासिल करने के लिए स्थैतिक चर का उपयोग कर सकते हैं और प्रत्येक पुनरावृत्ति के लिए कुछ अन्य लोगों को जानकारी दे सकते हैं।

यदि आप बहुत गहरे धकेलते हैं तो आपको सीगफॉल्ट का आश्वासन दिया जाता है (यदि आपके पास एमएमयू है)।

ध्यान दें कि malloc() जब सिस्टम मेमोरी से बाहर हो जाता है तो NULL (जो भी असाइन किया गया है तो segfault भी) लौटाता है और अधिक नहीं। यानी आप सभी कर सकते हैं जमानत या बस इसे किसी भी तरह से असाइन करने का प्रयास करें।

उपयोग करने के लिए malloc()मैं ग्लोबल्स का उपयोग करता हूं और उन्हें NULL असाइन करता हूं। अगर पॉइंटर NULL नहीं है तो मैं इसे इस्तेमाल करने से पहले मुफ्त करता हूंmalloc()

यदि आप realloc()किसी मौजूदा डेटा की प्रतिलिपि चाहते हैं तो आप सामान्य स्थिति के रूप में भी उपयोग कर सकते हैं । यदि आप प्रतिलिपि बनाने या जा रहे हैं, तो वर्कआउट करने से पहले आपको पॉइंटर को जांचना होगाrealloc()

३.२.५.२ सर्वार्थ लाभः


4
वास्तव में एलोका कल्पना यह नहीं कहती है कि यह असफल (स्टैक ओवरफ्लो) पर एक अमान्य पॉइंटर देता है, यह कहता है कि इसमें अपरिभाषित व्यवहार है ... और मॉलॉक के लिए यह कहता है कि यह NULL देता है, न कि एक यादृच्छिक अमान्य पॉइंटर (ठीक है, लिनक्स आशावादी मेमोरी कार्यान्वयन) निकम्मा)।
क्रिस् स।

@kriss Linux आपकी प्रक्रिया को मार सकता है, लेकिन कम से कम यह अपरिभाषित व्यवहार में उद्यम नहीं करता है
craig65535

@ craig65535: अभिव्यक्ति अपरिभाषित व्यवहार का आमतौर पर मतलब है कि व्यवहार C या C ++ विनिर्देश द्वारा परिभाषित नहीं है। किसी भी तरह से नहीं कि यह किसी भी ओएस या कंपाइलर पर यादृच्छिक या अस्थिर होगा। इसलिए यूबी को "लिनक्स" या "विंडोज" जैसे ओएस के नाम के साथ जोड़ना अर्थहीन है। इसका उससे कोई लेना-देना नहीं है।
क्रिश

मैं यह कहने की कोशिश कर रहा था कि मॉलॉक NULL को वापस कर रहा है, या लिनक्स के मामले में, आपकी प्रक्रिया को मारने वाली मेमोरी एक्सेस, एलोका के अपरिभाषित व्यवहार के लिए बेहतर है। मुझे लगता है कि मुझे आपकी पहली टिप्पणी गलत लगी होगी।

3

प्रक्रियाओं में केवल सीमित मात्रा में स्टैक स्थान उपलब्ध है - उपलब्ध स्मृति की मात्रा से कम malloc()

आपके द्वारा alloca()नाटकीय रूप से स्टैक ओवरफ्लो त्रुटि होने की संभावना को बढ़ाकर (यदि आप भाग्यशाली हैं, या यदि आप नहीं हैं तो अकथनीय दुर्घटना हो सकती है)।


यह आवेदन पर बहुत निर्भर करता है। यह एक मेमोरी-सीमित एम्बेडेड एप्लिकेशन के लिए एक ढेर आकार से बड़ा होना असामान्य नहीं है (यदि वहाँ भी एक ढेर है)।
एब्लैक

3

बहुत सुंदर नहीं है, लेकिन अगर प्रदर्शन वास्तव में मायने रखता है, तो आप स्टैक पर कुछ जगह का प्रचार कर सकते हैं।

यदि आप पहले से ही अब मेमोरी का अधिकतम आकार अपनी जरूरत को रोकते हैं और आप ओवरफ्लो की जांच करना चाहते हैं, तो आप कुछ ऐसा कर सकते हैं:

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}

12
क्या किसी भी प्रकार के डेटा के लिए चार वर्णों को सही ढंग से संरेखित करने की गारंटी है? एलोका ऐसा वादा प्रदान करता है।
जुहो Justman

@ Juho ofstman: यदि आपके पास संरेखण समस्याएँ हैं, तो आप एक सरणी की संरचना (या जो भी प्रकार) का उपयोग कर सकते हैं।
क्रिस् स।

यह एक चर लंबाई सरणी कहा जाता है । C90 और इसके बाद के संस्करण में समर्थित है, लेकिन C ++ नहीं। देखें Can मैं सी ++ 03 और सी ++ 11 में एक सी चर लंबाई सरणी का उपयोग करें?
jww

3

अलोका फ़ंक्शन बहुत अच्छा है और सभी naysayers केवल FUD का प्रसार कर रहे हैं।

void foo()
{
    int x = 50000; 
    char array[x];
    char *parray = (char *)alloca(x);
}

Array और parray बिल्कुल समान जोखिम वाले समान हैं। यह कहना कि एक दूसरे की तुलना में बेहतर है, एक तकनीकी विकल्प है, न कि तकनीकी।

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

यह बुरा क्यों है?


3

दरअसल, स्टैक का उपयोग करने के लिए एलोका की गारंटी नहीं है। वास्तव में, ऑलोक का gcc-2.95 कार्यान्वयन, मॉलोक का उपयोग करके हीप से मेमोरी आवंटित करता है। इसके अलावा कि कार्यान्वयन छोटी गाड़ी है, यह मेमोरी रिसाव और कुछ अप्रत्याशित व्यवहार को जन्म दे सकता है यदि आप इसे गोटो के आगे उपयोग के साथ ब्लॉक के अंदर कहते हैं। ऐसा नहीं है, यह कहने के लिए कि आपको इसका उपयोग कभी नहीं करना चाहिए, लेकिन कुछ समय के बाद एलोवेरा की तुलना में अधिक उपरि की ओर जाता है।


ऐसा लगता है जैसे gcc-2.95 ने alloca को तोड़ दिया है और संभवतः उन कार्यक्रमों के लिए सुरक्षित रूप से उपयोग नहीं किया जा सकता है जिनकी आवश्यकता है alloca। जब longjmpयह किया गया फ्रेम को त्यागने के लिए उपयोग किया जाता है तो यह मेमोरी को कैसे साफ करेगा alloca? आज कोई भी व्यक्ति जीसीसी 2.95 का उपयोग कैसे करेगा?
कज़

2

IMHO, अलोका को बुरा अभ्यास माना जाता है क्योंकि हर कोई स्टैक आकार सीमा को समाप्त करने से डरता है।

मैंने इस सूत्र और कुछ अन्य लिंक्स को पढ़कर बहुत कुछ सीखा:

मैं मुख्य रूप से अपने सादे सी फ़ाइलों को msvc पर संकलित करने के लिए और बिना किसी परिवर्तन, C89 शैली, बिना #ifdef _MSC_VER, आदि के उपयोग के लिए alloca का उपयोग करता हूं।

धन्यवाद ! इस धागे ने मुझे इस साइट पर प्रवेश कराया :)


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

1

मेरी राय में, एलोका (), जहां उपलब्ध है, केवल एक विवश तरीके से उपयोग किया जाना चाहिए। "गोटो" के उपयोग को बहुत पसंद करते हैं, बहुत बड़ी संख्या में अन्यथा उचित लोगों के पास न केवल उपयोग करने के लिए, बल्कि अलोक () का अस्तित्व भी मजबूत है।

एम्बेडेड उपयोग के लिए, जहां स्टैक आकार ज्ञात है और आवंटन के आकार पर कन्वेंशन और विश्लेषण के माध्यम से सीमाएं लगाई जा सकती हैं, और जहां संकलक को C99 + का समर्थन करने के लिए अपग्रेड नहीं किया जा सकता है, एलोका का उपयोग () ठीक है, और मैं कर रहा हूं इसका उपयोग करने के लिए जाना जाता है।

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

स्टैक पर डेटा और रिटर्न एड्रेस / फ्रेम पॉइंटर्स स्टोर करने वाले आर्किटेक्चर पर (जो मुझे पता है, उन सभी में से है), कोई भी स्टैक आवंटित चर खतरनाक हो सकता है क्योंकि वेरिएबल का पता लिया जा सकता है, और अनियंत्रित इनपुट मानों की अनुमति हो सकती है हर तरह की शरारत।

पोर्टेबिलिटी एम्बेडेड स्पेस में एक चिंता का कम है, हालांकि यह सावधानी से नियंत्रित परिस्थितियों के बाहर एलोका () के उपयोग के खिलाफ एक अच्छा तर्क है।

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


1

यहां ज्यादातर जवाब मुख्य रूप से इस बिंदु को याद करते हैं: एक कारण है कि क्यों का उपयोग _alloca()करना संभवतः स्टैक में केवल बड़ी वस्तुओं को संग्रहीत करने से भी बदतर है।

स्वचालित भंडारण के बीच मुख्य अंतर _alloca()यह है कि बाद वाली एक अतिरिक्त (गंभीर) समस्या से ग्रस्त है: आवंटित ब्लॉक को कंपाइलर द्वारा नियंत्रित नहीं किया जाता है , इसलिए कंपाइलर के पास इसे अनुकूलित या रीसायकल करने का कोई तरीका नहीं है।

की तुलना करें:

while (condition) {
    char buffer[0x100]; // Chill.
    /* ... */
}

साथ में:

while (condition) {
    char* buffer = _alloca(0x100); // Bad!
    /* ... */
}

उत्तरार्द्ध के साथ समस्या स्पष्ट होनी चाहिए।


क्या आपके पास वीएलए और alloca(हां, मैं वीएलए कहती हूं, क्योंकि अंतर allocaसांख्यिकीय आकार के रचनाकारों की तुलना में अधिक है) के बीच अंतर प्रदर्शित करने वाले कोई भी व्यावहारिक उदाहरण हैं ?
रुस्लान

दूसरे के लिए उपयोग के मामले हैं, जो पहले का समर्थन नहीं करता है। लूप 'एन' बार चलने के बाद मैं 'एन' रिकॉर्ड रखना चाहता हूं - शायद एक लिंक्ड-लिस्ट या ट्री में; यह डेटा संरचना तब निपटाया जा रहा है जब फ़ंक्शन अंततः लौटता है। यह कहने के लिए नहीं है कि मैं कुछ भी इस तरह से कोड
करुँगा

1
और मैं कहूंगा कि "संकलक इसे नियंत्रित नहीं कर सकता है" क्योंकि वह तरीका है कि एलोका () परिभाषित है; आधुनिक संकलक जानते हैं कि एलोका क्या है, और इसे विशेष रूप से व्यवहार करें; यह सिर्फ 80 के दशक की तरह एक पुस्तकालय समारोह नहीं था। C99 वीएलए मूल रूप से ब्लॉक स्कोप (और बेहतर टाइपिंग) के साथ आवंटित हैं। कोई अधिक या कम नियंत्रण नहीं, बस अलग-अलग शब्दार्थों के अनुरूप।
ग्रोगो

@greggo: यदि आप निराश हैं, तो मुझे ख़ुशी होगी कि आपको क्यों लगता है कि मेरा उत्तर उपयोगी नहीं है।
ऐलेकोव

सी में, रीसाइक्लिंग संकलक का कार्य नहीं है, इसके बजाय यह सी लाइब्रेरी (मुक्त ()) का कार्य है। एलोका () वापसी पर मुक्त किया जाता है।
पीटर - मोनिका

1

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

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

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