2011-01-28 18 views
8

मेरे पास BaseClass में एक रिकर्सिव फ़ंक्शन है जो protected virtual फ़ंक्शन की वापसी स्थिति के लिए फ़ंक्शन पर निर्भर करता है।रिकर्सिव फ़ंक्शंस में स्टैक ओवरव्लो को रोकना

बच्चे के वर्ग के लिए यह कार्य गलत तरीके से ओवरराइड करना संभव है और StackOverFlow अपवाद की ओर जाता है। सबसे बुरी बात यह है कि कुछ धीमी नेटवर्क कॉल हैं और अपवाद जल्द ही नहीं होने वाला है (कई संसाधन लंबे समय तक बर्बाद हो जाते हैं)।

मैं बेस क्लास में शुरुआती चरणों में StackOverFlow को जांचने के लिए एक विधि की तलाश कर रहा हूं (शायद Reflection और वर्तमान रिकर्सन स्तर का उपयोग कर)।

कोई विचार?

+0

^स्टैक ओवरफ्लो के बारे में विषय के लिए वोट दें। – Robino

उत्तर

8

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

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

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

+3

कोई रास्ता नहीं, इयान मर्सर यहां पोस्ट करते हैं? – Pierreten

+0

'बूल रिकर्सिव कंडिशन मोड (रेफरी गहराई गहराई) {गहराई ++; // अगर (गहराईLevel> MAX_DEPTH_LEVEL) लूप तोड़ें 'क्या यह ठीक है? – Xaqron

+3

@Xaqron, मैं इस तरह के रेफ इंट का उपयोग नहीं करता। जब मैं विधि स्वयं कॉल करता हूं और विधि के अंदर गहराई की पहली चीज़ की जांच करता हूं तो मैं गहराई + 1 गुजरता हूं। उदाहरण के लिए एक वृक्ष खोज में आप शायद कुल नोड्स को सीमित नहीं करना चाहते हैं, लेकिन आप यह सुनिश्चित करना चाहते हैं कि यह कुछ लूप में फंस न जाए क्योंकि पेड़ एक उचित पेड़ नहीं था। –

1

वर्कअराउंड बनाने की बजाय समस्या हल करें। एक निजी फ़ंक्शन बनाएं जो रिकर्सिव है जो संरक्षित वर्चुअल फ़ंक्शन को कॉल करता है।

+0

कोई रास्ता नहीं। वापसी की स्थिति रन-टाइम तक बेस क्लास में प्रकट नहीं होती है और यह उस विधि को ओवरराइड करके बाल वर्ग द्वारा प्रदान की जाती है। – Xaqron

+0

? आपकी बेस क्लास को बाल कक्षाओं पर लागू होने पर क्यों लागू किया जाना चाहिए? – Pierreten

+1

चाइल्ड क्लास बेस क्लास के माध्यम से बहुत सारे काम प्लग-इन साझा कर रहे हैं। अगर किसी बच्चे को गहराई से जाने की ज़रूरत है, तो इसकी अनुमति है लेकिन कोड स्वयं बेस क्लास के अंदर है और बच्चों के बीच साझा किया जाता है। – Xaqron

0

हालांकि आप शायद कॉल स्टैक पढ़ सकते हैं और इसका विश्लेषण कर सकते हैं, मैं ऐसा नहीं करूँगा।

  1. यह निष्पादन
  2. धीमी हो जाएगी यह अपने आधार वर्ग नहीं है 'जिम्मेदारी
  3. दस्तावेज़ अपने आधार वर्ग के व्यवहार

एक वैकल्पिक डिबग मोड में कॉल स्टैक विश्लेषण करने के लिए हो सकता है केवल। कॉल स्टैक कैसे प्राप्त करें यह देखने के लिए यहां एक छोटा कोड है।

using System.Diagnostics; 

[STAThread] 
public static void Main() 
{ 
    StackTrace stackTrace = new StackTrace();   // get call stack 
    StackFrame[] stackFrames = stackTrace.GetFrames(); // get method calls (frames) 

    // write call stack method names 
    foreach (StackFrame stackFrame in stackFrames) 
    { 
    Console.WriteLine(stackFrame.GetMethod().Name); // write method name 
    } 
} 

From this site

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