2010-04-13 10 views
41

पायथन में अधिकतम रिकर्सन गहराई है। ऐसा लगता है क्योंकि पाइथन एक दुभाषिया है, संकलक नहीं। क्या सी ++ में एक ही अवधारणा है? या यह केवल राम सीमा के साथ जुड़ा हुआ है?क्या सी ++ रिकर्सन गहराई को सीमित करता है?

+2

मुझे लगता है कि आपका मतलब है * अधिकतम * रिकर्सन गहराई। (आपको किसी त्रुटि का सामना करने से पहले कितनी गहरी रिकर्सन की अनुमति है) – jalf

+1

मैं नहीं देख रहा हूं कि एक दुभाषिया/कंपाइलर होने के कारण इसका कोई संबंध नहीं होगा। उदाहरण के लिए, स्टैकलेस पायथन अभी भी एक दुभाषिया है, लेकिन सी स्टैक फ्रेम के लिए सी स्टैक का उपयोग नहीं करता है और इसलिए एक ही समस्या नहीं है, नहीं? – Ken

+0

नोट करें कि सी ++ और पायथन कार्यान्वयन हैं जो उन मामलों में स्टैक सीमाओं से बचने के लिए पूंछ कॉल उन्मूलन कर सकते हैं। –

उत्तर

39

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

ढेर सीमा आमतौर पर ओएस स्तर पर ट्यून करने योग्य है। (यदि आप यूनिक्स पर हैं तो ulimit शैल बिल्ट-इन के लिए दस्तावेज़ देखें।) इस मशीन पर डिफ़ॉल्ट (ओएसएक्स) 8 एमबी है।

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

+2

मुझे पता है कि मुझे इकाइयों के लिए एमआईबी कहा जाना चाहिए था, लेकिन इसका मतलब है कि पूरी तरह से मेरे लिए कुछ और है। तो मैं इसके बजाय 67.1 मेगाबिट के लिए जाऊंगा! –

+0

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

+0

मुझे लगता है कि इस क्षेत्र में दो ओएस परिवार वर्चुअल मेमोरी को कैसे संभालेंगे इसमें अंतर है। विवरण बदले में गैर-तुच्छ होना शुरू होता है। –

3

सी ++ में अधिकतम रिकर्सन गहराई है, जो स्टैक द्वारा सीमित है। हालांकि, आधुनिक ऑपरेटिंग सिस्टम उपयोगकर्ता स्थान स्टेक को गतिशील रूप से विस्तारित करने में सक्षम होते हैं, क्योंकि यह मेमोरी स्पेस और मेमोरी विखंडन द्वारा रिकर्सन गहराई को सीमित करता है।

+1

हम्म .. मैं पूरी तरह से सकारात्मक नहीं हूं यूनिक्सन उस सुविधा प्रदान करते हैं। लेकिन मैं बहुत गलत हो सकता था :) ऐसा लगता है कि 'बूस्ट :: रेगेक्स' ऐसी सुविधाओं का उपयोग करेगा यदि वे उपलब्ध थे ... यह विंडोज़ पर उनका उपयोग करता है। –

+0

गतिशील ढेर विस्तार दिलचस्प लगता है। क्या आपके पास कोई संदर्भ है? –

+0

@ डॉन वेकफील्ड: http://support.microsoft.com/kb/315937 –

3

मुझे विश्वास है कि सीमा मंच पर उपलब्ध स्टैक का आकार है। मैंने जो पढ़ा है, उससे लिनक्स पर डिफ़ॉल्ट रूप से 8K 8MB है, लेकिन आधुनिक कर्नल गतिशील रूप से स्टैक आकार को समायोजित कर सकते हैं।

+2

8K एक ढेर के लिए सुंदर उथला है। मैंने सोचा कि इसका मतलब है कि यह 8 के लिए शुरू होता है और पृष्ठों द्वारा फैलता है। –

+0

वास्तव में यह डिफ़ॉल्ट रूप से 8 एम है :) –

+0

असल में 8 एमबी हो सकता है - जो लेख मैंने पढ़ा था वह स्पष्ट नहीं था। –

6

सी या सी ++ मानकों में कोई रिकर्सन गहराई ट्रैकिंग या सीमा नहीं है। रनटाइम पर, गहराई तक सीमित है कि ढेर कितना बड़ा हो सकता है।

+0

असल में, सीमा प्लेटफॉर्म की संबोधित क्षमता, प्रक्रिया के लिए उपलब्ध स्मृति की मात्रा और कंपाइलर द्वारा निर्धारित किसी भी सीमा का संयोजन है। आम तौर पर, अनुप्रयोग ढेर को ओवरराइड कर सकते हैं और अपरिभाषित व्यवहार कर सकते हैं। –

+0

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

19

नहीं, सी ++ में स्पष्ट रिकर्सन गहराई नहीं है। यदि अधिकतम स्टैक आकार पार हो गया है (जो विंडोज़ पर डिफ़ॉल्ट रूप से 1 एमबी है), तो आपका सी ++ प्रोग्राम आपके ढेर को ओवरफ्लो करेगा और निष्पादन समाप्त कर दिया जाएगा।

+3

हाँ। +1। इसके अतिरिक्त, यह ध्यान रखना महत्वपूर्ण है कि समाप्ति तत्काल है - कॉलिनेट प्रोसेसिंग कॉल करने के समान। आपकी कोई भी प्रक्रिया 'अच्छी शट डाउन फीचर्स (यानी DLL_PROCESS_DETACH, DLL_THREAD_DETACH, आदि) को कॉल किया जाएगा। –

+3

बिल्कुल - यह एक नास्टियर तरीकों में से एक है जिसे एक कार्यक्रम समाप्त किया जा सकता है। –

3

पायथन के पास रिकर्सिव कॉल पर tunable limit है, जबकि सी ++ स्टैक आकार से सीमित है।

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

int fact(int n, int accum=1){ 
    if (n==0) return accum; 
    else return fact(n-1,n*accum); //tail recursion here. 
} 

अजगर पूंछ प्रत्यावर्तन का अनुकूलन नहीं करता है (लेकिन stackless Python करता है), और सी ++ करता है पूंछ रिकर्सन ऑप्टिमाइज़ेशन की आवश्यकता नहीं है, लेकिन मेरा मानना ​​है कि जीसीसी पूंछ रिकर्सन को अनुकूलित करता है। जेवीएम पूंछ रिकर्सन को अनुकूलित नहीं करता है, हालांकि स्कैला भाषा कुछ सामान्य दस्तावेज मामलों में होती है। योजना और लिस्प (और शायद अन्य कार्यात्मक भाषाओं के साथ) की आवश्यकता है कि पूंछ रिकर्सन अनुकूलित किया जाए।

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