2009-10-17 21 views
6

रिकर्सन का उपयोग किए बिना एक स्टैक ओवरफ़्लो अपवाद कैसे फेंक दिया जा सकता है?रिकर्सन का उपयोग किए बिना एक स्टैक ओवरफ़्लो अपवाद कैसे फेंक दिया जा सकता है?

+0

दोहराए सवाल शरीर के लिए क्षमा करें, लेकिन मैं जोड़ने के लिए लायक है, जबकि कुछ भी नहीं सोच सकता था। – JaredCacurak

+0

यह ठीक है। मैं अक्सर खुद को एक ही स्थिति में पाया :) – pierrotlefou

+0

आप हमेशा शरीर में एनटी (कोई पाठ) डाल सकते हैं। वह हमेशा बीबीएस दिनों में काम करता था। –

उत्तर

12

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

16

एक स्थानीय चर के रूप में एक ENORMOUS सरणी घोषित करें।

+0

अधिकांश कंपाइलर्स बस इसे संकलित नहीं करेंगे। यह एक ढेर ओवरफ्लो नहीं है। –

+1

@ क्रिस - इसे संकलित नहीं करेंगे? मैंने सोचा कि अधिकतम स्टैक आकार लिंकर द्वारा सेट किया गया था, और संकलक को ज्ञात नहीं है। – ChrisW

+2

संकलक इसे पकड़ नहीं सकता है, जब तक कि संकलक अनुमानित रन-टाइम स्टैक उपयोग के लिए कोड का विश्लेषण करने में सक्षम न हो, जो बेहद मुश्किल हो सकता है। – JustJeff

2

प्रत्येक विधि कॉल जो अभी तक वापस नहीं आई है कुछ स्टैक स्पेस का उपभोग करता है। (अधिक स्थानीय चर के साथ के तरीके अधिक जगह का उपभोग करते हैं।) एक बहुत गहरी कॉल स्टैक का परिणाम स्टैक ओवरफ़्लो हो सकता है।

ध्यान दें कि सीमित मेमोरी (मोबाइल डिवाइस और ऐसे) वाले सिस्टम पर आपके पास अधिक स्टैक स्पेस नहीं है और जल्द ही बाहर निकल जाएगा।

+1

मैंने एक कंसोल प्रोजेक्ट पर काम किया जहां हमारी प्रक्रियाओं में 32 के ढेर थे। दिनचर्या में से एक में दो 16 के सरणी थीं। हालांकि सरणी का उपयोग अनन्य था और वे एक ही दायरे में नहीं थे, फिर भी कंपाइलर ने 32k स्टैक स्पेस आवंटित किया और हमारे ढेर को ओवरफ्लो किया (सैद्धांतिक रूप से एक स्मार्ट कंपाइलर केवल 16K आरक्षित होगा)। मैंने समस्या को ठीक करने के लिए उन्हें आवंटित/मुक्त दोनों में बदल दिया। – Adisak

20

के बाद से और कोई नहीं यह उल्लेख किया गया है:

throw new System.StackOverflowException(); 

आप इस जब परीक्षण या गलती इंजेक्शन कर कर सकता है।

+1

ग्रेट - मान लीजिए कि आप .NET =) –

1

आप ++ एक उचित मानक पुस्तकालय के साथ, मैं छवि है कि इस काम करेगा सी के बारे में बात कर रहे हैं: alloca पर

while (true) { 
    alloca(1024 * 1024); // arbitrary - 1M per iteration. 
} 

विवरण।

+0

का उपयोग कर रहे हैं क्या यह एक स्टैक ओवरफ्लो या स्मृति अपवाद से बाहर है? – Juliet

+2

@ जुलिएट: एलोका() फ़ंक्शन कॉलर के स्टैक फ्रेम में स्थान आवंटित करता है। – pierrotlefou

+2

अगर एलोका() ठीक से लागू किया गया है तो इसे अपवाद नहीं फेंकना चाहिए। यदि कॉल अपवाद को फेंकने के बजाय पर्याप्त स्टैक स्पेस नहीं है तो कॉल एलोका() को पूर्ण वापस जाना चाहिए। क्या होना चाहिए कि स्टैक स्पेस से बाहर निकलने के बाद, आपका कोड एनओएलएल लौटने वाले एलोका() कॉल के अनंत लूप में फंस जाएगा। – Adisak

2

संक्षिप्त उत्तर: यदि आपके पास कोई ऑब्जेक्ट है जो आंतरिक ऑब्जेक्ट कहता है, तो आप स्टैक ट्रेस को 1 तक बढ़ाते हैं। इसलिए, यदि आपके पास एक दूसरे के अंदर घोंसले हुए ऑब्जेक्ट्स हैं, तो प्रत्येक अपनी आंतरिक ऑब्जेक्ट को कॉल करता है, अंततः आपको मिल जाएगा एक ढेर अतिप्रवाह।

यहाँ कैसे नेस्टेड iterators का उपयोग कर अभाज्य संख्या उत्पन्न करने के लिए का एक प्रदर्शन है:

using System; 
using System.Collections.Generic; 
using System.Text; 

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Program p = new Program(); 

      IEnumerator<int> primes = p.AllPrimes().GetEnumerator(); 
      int numberOfPrimes = 1000; 
      for (int i = 0; i <= numberOfPrimes; i++) 
      { 
       primes.MoveNext(); 
       if (i % 1000 == 0) 
       { 
        Console.WriteLine(primes.Current); 
       } 
      } 
      Console.ReadKey(true); 
     } 

     IEnumerable<int> FilterDivisors(IEnumerator<int> seq, int num) 
     { 
      while (true) 
      { 
       int current = seq.Current; 
       if (current % num != 0) 
       { 
        yield return current; 
       } 
       seq.MoveNext(); 
      } 
     } 

     IEnumerable<int> AllIntegers() 
     { 
      int i = 2; 
      while (true) 
      { 
       yield return i++; 
      } 
     } 

     IEnumerable<int> AllPrimes() 
     { 
      IEnumerator<int> nums = AllIntegers().GetEnumerator(); 
      while (true) 
      { 
       nums.MoveNext(); 
       int prime = nums.Current; 
       yield return prime; 

       // nested iterator makes a big boom  
       nums = FilterDivisors(nums, prime).GetEnumerator(); 
      } 
     } 
    } 
} 

कोई प्रत्यावर्तन नहीं है, लेकिन कार्यक्रम के आसपास 150,000 अभाज्य संख्या के बाद एक ढेर अतिप्रवाह अपवाद फेंक देते हैं।

+0

एनसीआई कोड, मुझे हास्केल प्रोग्रामर के विकास की याद दिलाता है :) (ऑनलाइनर के खिलाफ कोड का टन - प्रोग्रामिंग एक फैक्टोरियल) –

7

निम्नलिखित विंडोज पर लागू होता है, लेकिन अधिकांश ओएस इसे समान रूप से लागू करते हैं।

संक्षिप्त उत्तर यह है: यदि आप अंतिम गार्ड पेज को स्पर्श करते हैं, तो यह फेंक देगा।

(C00000FD) प्रकार EXCEPTION_STACK_OVERFLOW की एक अपवाद उठाया है जब आपके आवेदन ढेर के नीचे पेज को छू लेती है, कि एक PAGE_GUARD सुरक्षा ध्वज चिह्नित है, और कोई जगह ढेर विकसित करने के लिए नहीं है (एक और पेज के लिए प्रतिबद्ध), देखना How to trap stack overflow in a Visual C++ application
जब ऐसा होता है तो सामान्य मामला तब होता है जब स्टैक पर कई फ़ंक्शन फ़्रेम (यानी नियंत्रण रिकर्सन से बाहर) के परिणामस्वरूप ढेर उगाया जाता है, कम फ्रेम के परिणामस्वरूप, लेकिन बहुत बड़े फ्रेम आकार (बहुत बड़े होते हैं स्थानीय स्कोप्ड ऑब्जेक्ट) या _alloca के साथ स्टैक से स्पष्ट रूप से आवंटित करके।
अपवाद का कारण बनने का एक और तरीका जानबूझकर गार्ड पेज को स्पर्श करना है, उदाहरण के लिए। उस पृष्ठ पर इंगित करने वाले पॉइंटर को संदर्भित करके। यह परिवर्तनीय प्रारंभिक बग के कारण हो सकता है।

इनपुट निष्पादन पथ पर स्टैक ओवरफ़्लो हो सकता है यदि इनपुट बहुत गहरा घोंसला स्तर का कारण बनता है।मिसाल के तौर पर देखते हैं Stack overflow occurs when you run a query that contains a large number of arguments inside an IN or a NOT IN clause in SQL Server.

-1

सबसे आसान तरीका एक StackOverflowException बनाने के लिए किया जाता है निम्नलिखित:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace ConsoleApplication2 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      SomeClass instance = new SomeClass(); 
      string name = instance.Name; 
     } 
    } 

    public class SomeClass 
    { 
     public string Name 
     { 
      get 
      { 
       return Name; 
      } 
     } 
    } 
} 
+1

असल में अपवाद फेंकने के बाद यह दूसरा सबसे आसान तरीका है :) –

+3

प्रश्न विशेष रूप से रिकर्सन को बाहर रखा गया है। – meriton

+0

आप सही हैं, मेरी गलती। –

0
int main() 
{ 
    //something on the stack 
    int foo = 0; 
    for (
    //pointer to an address on the stack 
    int* p = &foo; 
    //forever 
    ; 
    //ever lower on the stack (assuming that the stack grows downwards) 
    --p) 
    { 
    //write to the stack 
    *p = 42; 
    } 
} 
संबंधित मुद्दे