2010-03-03 12 views
6

ऑपरेटिंग सिस्टम में वास्तव में क्या होता है? एक पुनरावर्ती समारोह के लिए एक ढेर ओवरफ्लो और जबकि (1) के लिए? मुझे सही जवाब दो अगर मैं गलत हूँ?जबकि (1) अनंत लूप और एक पुनरावर्ती समारोह के बीच क्या अंतर है?

+1

स्टैक ओवरव्लो पर निर्भर करता है? – Broam

+8

स्टैक ओवरफ़्लो के बारे में एक प्रश्न ... शायद यह stackoverflow.com के लिए एक है? – Kez

उत्तर

1

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

+4

बिल्कुल सही नहीं है। एक पुनरावर्ती समारोह खुद को, अवधि कहते हैं। एक विशेष गैर-पुनरावर्ती खंड होने की आवश्यकता नहीं है। – Stephan202

+0

एक रिकर्सिव फ़ंक्शन __ को समाप्त नहीं करता है, लेकिन किसी भी रिकर्सिव फ़ंक्शन जो कुछ उपयोगी करता है, कुछ समय समाप्त हो जाएगा। एक ढेर ओवरफ्लो एक बहुत ही उपयोगी कार्यक्रम परिणाम नहीं है। – stakx

+0

तुलना थोड़ी देर (1) लूप के लिए है, इसलिए ऐसा लगता है कि वह इसे "हमेशा के लिए" चलाने का इरादा रखता है। – Joel

3

एक रिकर्सिव फ़ंक्शन स्वयं को कॉल करता रहता है जबकि एक अनंत लूप कोड के समान ब्लॉक को दोहराता रहता है।

जब कोई फ़ंक्शन कॉल किया जाता है, तो कुछ संग्रहण function call stack पर अपने वापसी मूल्य को संग्रहीत करने के लिए आरक्षित होना चाहिए। इसलिए, फ़ंक्शन के पर्याप्त रिकर्सिव इनवोकेशन दिए जाने पर, स्टैक स्पेस समाप्त हो जाएगा और एक स्टैक ओवरफ़्लो हो जाएगा।

पर विचार करें

#include <stdlib.h> 
#include <stdio.h> 

int somefunc(int x) { 
    printf("%d\n", x); 
    return somefunc(rand()); 
} 

int main(void) { 
    return somefunc(0); 
} 

कार्यक्रम ऊपर अंत में समाप्त या के रूप में

int somefunc(int x) { 
    return printf("%d\n", x); 
} 

int main(void) { 
    while (1) { 
     somefunc(rand()); 
    } 
    return 0; 
} 

जो खुशी से जब तक उपयोगकर्ता (समाप्ति का कारण बनता है CTRL-C दबाकर चलेंगे करने का विरोध कुछ गंभीर नुकसान नहीं होगा या कंप्यूटर बंद करना।)

+0

जाहिर है! मुझे नहीं लगता कि यह वह जवाब है जिसे वह ढूंढ रहा है। –

14

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

+3

+1 वास्तव में स्टैक –

+0

के बारे में अधिक जानकारी प्रदान करने के लिए स्टैक भरना संकलक और कोड संरचना पर निर्भर करता है। पूंछ रिकर्सन नामक एक सामान्य अनुकूलन, तब होता है जब रिटर्न रिकर्सिव कॉल के समान लाइन पर होती है। पूंछ कॉल रिकर्सन – lod

8

एक रिकर्सिव फ़ंक्शन स्वयं को कॉल करता है, जो स्टैक पर पैरामीटर को धक्का देता है। यह हमेशा के लिए जा सकता है, अंततः एक ढेर अतिप्रवाह की ओर अग्रसर। कुछ कंपाइलर्स इसे दूर करने के लिए अनिवार्य रूप से रिकर्सिव फ़ंक्शन को थोड़ी देर में बदल सकते हैं - इसे पूंछ रिकर्सन कहा जाता है।

जबकि पाश बस फिर से शीर्ष पर वापस जाना होगा और एक ही स्थान का पुन: उपयोग, तो यह सचमुच हमेशा के लिए चला सकते हैं (कम से कम जब तक सत्ता बाहर चला जाता है :-))

+4

+1 सटीक रूप से, रिकर्सिव का मतलब अनंत नहीं है। – ewernli

0

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

1

'जबकि (1)' अनंत लूप में, एक स्टैक फ्रेम के लिए स्टैक स्पेस आवंटित करेगा (फ़ंक्शन लौटने पर/कहां वापस लौटने के बारे में जानकारी) और उसी फ़ंक्शन में घोषित किए गए किसी भी स्थानीय चर लूप निष्पादित करने के कितने पुनरावृत्तियों के बावजूद स्टैक पर एक बार आवंटित किया गया।

इसलिए, 1000000 पुनरावृत्तियों के लिए, ढेर अंतरिक्ष sizeof (स्टैक फ्रेम) + sizeof (किसी भी स्थानीय चर)

इसलिए यदि स्टैक फ्रेम 16bytes है और पूर्णांक 4bytes है, समारोह 20bytes ढेर पर आवंटित होगा ।

जबकि, एक रिकर्सिव फ़ंक्शन स्टैक फ्रेम (फ़ंक्शन के बारे में जानकारी) के लिए स्टैक पर स्थान आवंटित करेगा और फ़ंक्शन कॉल होने पर प्रत्येक स्थानीय चर को आवंटित करेगा।

इसलिए, 1000000 पुनरावृत्तियों के लिए, ढेर अंतरिक्ष होगा (sizeof (स्टैक फ्रेम) + sizeof (किसी भी स्थानीय चर)) * 100000

20bytes तो (पिछले आकार का उपयोग करते हुए) * 1000000 == 20000000bytes == (लगभग) 1 9 एमबी

3

एक रिकर्सिव फ़ंक्शन समाप्त हो सकता है कि यह कैसे कोड किया गया है। बेशक, इसे एक ढेर ओवरफ्लो के साथ समाप्त करने की आवश्यकता नहीं है। while(1) पाश भी समाप्त हो सकता है अगर यह टूट जाता है या वापस आता है।

+1

के लिए – Pool

0

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

तो इस पर निर्भर पुनरावर्ती क्रिया आबंटित करता है में हर समारोह कॉल याद। तो आपको डिजाइन के दौरान सावधान रहना होगा।

जबकि (1) - प्रक्रिया के दौरान अनंत लूप के साथ प्रोग्राम निष्पादित करता है (1) {;} बस आदेशों के कुछ भाग को दोहराता है। ऐसी प्रक्रिया को ऑपरेटिंग सिस्टम में चलने वाले राज्य में रखना जो सीपीयू समय और कुछ मेमोरी लेता है।

0

सरल कोड और एक अच्छा कंपाइलर के लिए कोई फर्क नहीं पड़ता है, लेकिन एक गैर-टर्मिनल रिकर्सिव फ़ंक्शन के साथ एक निष्क्रिय कंपाइलर के लिए, आप स्टैक ओवरफ़्लो नामक स्टैक स्पेस से बाहर हो जाएंगे।

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

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

कहां-जैसे आपके पास एक गैर-पूर्व-खाली ओएस है, तो यह लटका होगा, अगर आप ओएस पर नियंत्रण वापस नहीं रखते हैं, तो विंडोज 3.1 दिनों में, प्रिंटर ड्राइवर मुद्रण करते समय पूरे सिस्टम को जमा कर देगा । वैसे एचपी ड्राइवरों ने किया।

सॉफ़्टवेयर लॉकिंग से बचने के लिए एम्बेडेड सिस्टम पर, आमतौर पर एक वॉचडॉग टाइमर नामक एक हार्डवेयर टाइमर होता है, जो कि हर सेकेंड 'टिकल' नहीं होता है, तो सिस्टम को रीबूट करेगा। इस प्रकार लॉक-अप स्थिति में रहने वाली प्रणाली को रोकना।

+0

असल में, अधिकांश सी कंपाइलर पूंछ रिकर्सन नहीं करते हैं क्योंकि इसका उपयोग सी कोड में ज्यादा नहीं होता है। बेशक अपवाद हैं (उदाहरण के लिए जीसीसी) लेकिन वे सिर्फ अपवाद हैं। – Joel

+0

"अच्छा" कंपाइलर और "बेवकूफ" शब्द के उपयोग पर ध्यान दें। मुझे याद है कि वाटकॉम कंपाइलर ने बहुत सी चीजें की हैं जो दूसरों ने नहीं की थी, आदि। शायद मैं बेहतर प्रदर्शन कर सकता था। –

0

while (1) एक नया मूल्यांकन संदर्भ नहीं बनाता है, रिकर्सन (जब तक संकलक द्वारा अनुकूलित नहीं किया जाता है) करता है। इसका अर्थ है कई चीजें:

  • सभी व्यावहारिक कार्यान्वयन में, एक नया मूल्यांकन संदर्भ नहीं बनाया जा सकता है (यानी एक स्टैक ओवरफ़्लो होता है)।
  • नए मूल्यांकन संदर्भ का अर्थ है कि आप घोषित किसी भी स्थानीय चर की नई प्रतियां।
  • while (1) से बाहर निकलने के लिए यह एक साधारण return के साथ बाहर निकलना मुश्किल है, लेकिन return केवल रिकर्सन में वर्तमान संदर्भ से बाहर निकलता है। बहुगुणित संदर्भों से गुजरने के लिए पूरी तरह से बाहर निकलना उतना छोटा नहीं है।
+0

अंतिम बिंदु के संबंध में, जिस स्थिति में फ़ंक्शन के पास केवल एक कॉल है, आप केवल उस कॉल के बिना लौटकर बाहर निकल सकते हैं। –

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