क्या 'छोरों' के लिए नेस्टेड की संख्या की सीमा है?


79

चूंकि सब कुछ की सीमा होती है, मैं सोच रहा था कि क्या नेस्टेड forलूप की संख्या की सीमा है या जब तक मेरे पास मेमोरी है, मैं उन्हें जोड़ सकता हूं, क्या विज़ुअल स्टूडियो कंपाइलर इस तरह का प्रोग्राम बना सकता है?

बेशक एक 64 या अधिक नेस्टेड forछोरों को डिबग करना आसान नहीं होगा, लेकिन क्या यह उचित है?

private void TestForLoop()
{
  for (int a = 0; a < 4; a++)
  {
    for (int b = 0; b < 56; b++)
    {
      for (int c = 0; c < 196; c++)
      {
        //etc....
      }
    }
  }
}

78
आप एक कंप्यूटर प्रोग्रामर हैं: कंप्यूटर प्रोग्रामिंग के साथ अपने स्वयं के प्रश्न का उत्तर दें। एक प्रोग्राम लिखें जो 1, 2, 4, 8, 16, 32, ... नेस्टेड लूप्स के साथ प्रोग्राम बनाता, संकलित करता है और चलाता है, और यदि कोई सीमा है, तो आप बहुत जल्दी सीख जाएंगे।
एरिक लिपर्ट

38
# 1 ओपी ने संकेत नहीं दिया है कि यह किसी भी तरह से उत्पादन कोड से संबंधित है, जैसा कि सिर्फ काल्पनिक, "क्या-अगर" प्रकार का सवाल है। # २। कोई फर्क नहीं पड़ता कि कितने नेस्टेड लूप्स का उपयोग करते समय ओपी बनाता है, वे कभी भी अनंत तक नहीं पहुंचेंगे; कोई फर्क नहीं पड़ता कि ओपी इसे कितना आगे बढ़ाता है, एकमात्र तरीका जो कभी भी साबित करेगा कि क्या कोई सीमा है और अगर यह वास्तव में टूट जाता है।
पैन्ज़रक्रिसिस

10
"चूंकि हर चीज की एक सीमा होती है", नहीं: sin (x) में x -> oo की सीमा नहीं है। इसके अलावा: यदि आपका आधार "सब कुछ बाध्य है", तो आप यह भी क्यों पूछ रहे हैं कि "क्या यह बात बाध्य है"? जवाब आपकी मान्यताओं में है जो तर्क को पूरी तरह से बेकार और तुच्छ बना देता है।
बकुरीउ

5
@EricLippert सख्ती से बोलना आपको यकीन नहीं होगा कि अगर कोई सीमा नहीं थी, तो कोई बात नहीं थी।
केसी

2
"x -> ऊँ" ने मुझे थोड़ा रुला दिया :) "x →
मनु

जवाबों:


120

मैं इसे पोस्ट करके एक अंग पर जा रहा हूं, लेकिन मुझे लगता है कि इसका जवाब है:

550 और 575 के बीच

Visual Studio 2015 में डिफ़ॉल्ट सेटिंग्स के साथ

मैंने एक छोटा सा प्रोग्राम बनाया जो नेस्टेड forलूप्स उत्पन्न करता है ...

for (int i0=0; i0<10; i0++)
{
    for (int i1=0; i1<10; i1++)
    {
        ...
        ...
        for (int i573=0; i573<10; i573++)
        {
            for (int i574=0; i574<10; i574++)
            {
                Console.WriteLine(i574);
            }
        }
        ...
        ...
    }
}

500 नेस्टेड छोरों के लिए, कार्यक्रम अभी भी संकलित किया जा सकता है। 575 छोरों के साथ, संकलक बाहर निकलता है:

चेतावनी AD0001 विश्लेषक 'Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames.CSharpSimplifyTamesNiDiagnosticAnalyzer' ने 'System.InsufficExecutionStackException' के एक अपवाद को फेंक दिया, संदेश के साथ अपर्याप्त स्टैक को सुरक्षित रूप से प्रोग्राम को जारी रखने के लिए। यह कॉल स्टैक पर बहुत अधिक फ़ंक्शन होने या स्टैक पर फ़ंक्शन बहुत अधिक स्टैक स्पेस का उपयोग करने से हो सकता है। '।

अंतर्निहित संकलक संदेश के साथ

CS8078 त्रुटि: एक अभिव्यक्ति संकलन के लिए बहुत लंबा या जटिल है

बेशक, यह एक विशुद्ध रूप से काल्पनिक परिणाम है। यदि अंतरतम लूप एक से अधिक हैConsole.WriteLine , तो स्टैक आकार से अधिक होने से पहले कम नेस्टेड लूप संभव हो सकते हैं। इसके अलावा, यह एक कड़ाई से तकनीकी सीमा नहीं हो सकती है, इस अर्थ में कि "विश्लेषक" के लिए अधिकतम स्टैक आकार बढ़ाने के लिए छिपी हुई सेटिंग्स हो सकती हैं, जो त्रुटि संदेश में उल्लिखित है, या (यदि आवश्यक हो) जिसके परिणामस्वरूप निष्पादन योग्य हो। हालांकि, उत्तर का यह हिस्सा उन लोगों के लिए छोड़ दिया गया है, जो C # को गहराई से जानते हैं।


अपडेट करें

टिप्पणी में सवाल के जवाब में :

मुझे यह साबित करने में दिलचस्पी होगी कि प्रयोगात्मक रूप से "साबित" किए गए इस जवाब को देखें कि क्या आप स्टैक पर 575 स्थानीय चर डाल सकते हैं, यदि उनका उपयोग लूप में नहीं किया जाता है, और / या आप 575 गैर-नेस्टेड -लूप में डाल सकते हैं या नहीं एक एकल समारोह

दोनों मामलों के लिए, उत्तर है: हां, यह संभव है। 575 ऑटो-जनरेटेड स्टेटमेंट के साथ विधि को भरने पर

int i0=0;
Console.WriteLine(i0);
int i1=0;
Console.WriteLine(i1);
...
int i574=0;
Console.WriteLine(i574);

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

त्रुटि CS0204: केवल 65534 स्थानीय लोगों, जिनमें कंपाइलर द्वारा उत्पन्न किया गया है, की अनुमति है

जो एक दिलचस्प बिंदु है, लेकिन पहले से ही कहीं और देखा गया है: विधि में चर की अधिकतम संख्या

इसी तरह, 575 गैर-नेस्टेड- for फ्लॉप, जैसा कि

for (int i0=0; i0<10; i0++)
{
    Console.WriteLine(i0);
}
for (int i1=0; i1<10; i1++)
{
    Console.WriteLine(i1);
}
...
for (int i574=0; i574<10; i574++)
{
    Console.WriteLine(i574);
}

साथ ही संकलित किया जा सकता है। यहाँ, मैंने भी सीमा खोजने की कोशिश की, और इनमें से अधिक छोरों का निर्माण किया। विशेष रूप से, मुझे यकीन नहीं था कि क्या इस मामले में लूप चर भी "स्थानीय लोगों" को गिनते हैं, क्योंकि वे अपने स्वयं के हैं { block }। लेकिन फिर भी, 65534 से अधिक संभव नहीं है। अंत में, मैंने एक परीक्षण जोड़ा जिसमें पैटर्न के 40000 लूप शामिल थे

for (int i39999 = 0; i39999 < 10; i39999++)
{
    int j = 0;
    Console.WriteLine(j + i39999);
}

इसमें लूप में एक अतिरिक्त वैरिएबल था , लेकिन ये "लोकल" के रूप में भी गिने जाते हैं, और इसे संकलित करना संभव नहीं था।


इसलिए संक्षेप में: ~ 550 की सीमा वास्तव में छोरों की घोंसले की गहराई के कारण होती है। यह भी त्रुटि संदेश द्वारा इंगित किया गया था

CS8078 त्रुटि: एक अभिव्यक्ति संकलन के लिए बहुत लंबा या जटिल है

त्रुटि CS1647 के प्रलेखनदुर्भाग्यवश (लेकिन समझ से) जटिलता के "माप" को निर्दिष्ट नहीं करता है, लेकिन केवल व्यावहारिक सलाह देता है

आपके कोड को संसाधित करने वाले कंपाइलर में स्टैक ओवरफ़्लो था। इस त्रुटि को हल करने के लिए, अपने कोड को सरल बनाएं।

इसे फिर से जोर देने के लिएfor : विशेष रूप से नेस्टेड- लूप के विशेष मामले के लिए , यह सब बल्कि अकादमिक और काल्पनिक है । लेकिन CS1647 के त्रुटि संदेश के लिए वेबसर्च करने से कई मामलों का पता चलता है, जहां यह त्रुटि कोड के लिए दिखाई दी, जो कि संभवतः सबसे जटिल रूप से जटिल नहीं थी, लेकिन यथार्थवादी परिदृश्यों में बनाई गई थी।


2
@PatrickHofman हां, संकेत "डिफ़ॉल्ट सेटिंग्स के साथ ..." महत्वपूर्ण है: यह वीएस2015 में एक डिफ़ॉल्ट परियोजना बनाने के लिए भोलेपन को संदर्भित करता है। प्रोजेक्ट सेटिंग्स ने सीमा बढ़ाने के लिए "स्पष्ट" पैरामीटर नहीं दिखाया। लेकिन इस बात की परवाह किए बिना, मुझे आश्चर्य है कि क्या सीएलआई / सीएलआर / जो कुछ भी है, उसके द्वारा आगे कोई सीमा नहीं है। ECMA-335 कल्पना कोई अनुभाग है "III.1.7.4 maxstack प्रदान करना होगा" , लेकिन मैं अभी तक बहुत ज्यादा एक सी # noob का कहना है कि क्या यह वास्तव में संबंधित है, या यहाँ तक कि विस्तार से इसका अर्थ विश्लेषण करने के लिए कर रहा हूँ ....
मार्को 13

10
ऐसा पहली बार नहीं होगा जब Microsoft ने forलूप्स की सीमा तय की हो । माइक्रोसॉफ्ट बुनियादी 8. की एक घोंसले सीमा था
मार्क

3
@ डेविड: त्रुटि संदेश संकलक में स्टैक आकार को संदर्भित करता है , जो एक कार्यक्रम भी है, और जो नेस्टेड-लूपेड निर्माण को पुन: संसाधित कर रहा है। यह (दृढ़ता से) संकलन के तहत कोड में स्थानीय चर की संख्या से बंधा नहीं है।
रुख

2
यह सिर्फ मैं हूँ? मुझे यह उत्तर बिलकुल प्रफुल्लित करने वाला लगता है! मैंने भी 42जवाब के रूप में सोचा होगा ।
सेमीरोनिर्गो

11
यह शायद ध्यान देने योग्य है कि 500 ​​नेस्टेड लूप प्रति लूप में केवल 2 पुनरावृत्तियों को मानते हैं और प्रति चक्र एक पुनरावृत्ति 4 GHz कंप्यूटर पर चलने के लिए लगभग 10 ^ 33 googol साल (10 ^ 133) ले जाएगा। ब्रह्मांड की आयु की तुलना करने के लिए लगभग 1.37 x 10 ^ 10 वर्ष है। यह देखते हुए कि नाभिकों के बारे में 10 ^ 40 साल में क्षय होने की भविष्यवाणी की जाती है, मैं कह सकता हूं कि वर्तमान हार्डवेयर उस लंबे समय तक नहीं बना है और आपको इस बीच कंप्यूटर को पुनरारंभ करने की आवश्यकता हो सकती है।
मैकीज पीचोटका

40

सी # भाषा विनिर्देश या सीएलआर में कोई कठिन सीमा नहीं है। आपका कोड पुनरावृत्ति के बजाय पुनरावृत्ति वाला होगा, जिससे एक स्टैक ओवरफ़्लो हो सकता है।

कुछ चीजें हैं जो एक सीमा के रूप में गिना जा सकता है, उदाहरण के लिए (आमतौर पर) intकाउंटर का आप उपयोग करेंगे, जो intप्रत्येक लूप के लिए एक मेमोरी आवंटित करेगा (और इससे पहले कि आप अपने पूरे स्टैक को ints के साथ आवंटित करें ...)। ध्यान दें कि उस का उपयोग intआवश्यक है और आप उसी चर का पुन: उपयोग कर सकते हैं।

जैसा कि मार्को द्वारा बताया गया है , वर्तमान थ्रेशोल्डर वास्तविक भाषा विनिर्देश या रनटाइम की तुलना में संकलक में अधिक है। एक बार जब पुनरावृत्ति होती है, तो आप कुछ अधिक पुनरावृत्तियों के साथ हो सकते हैं। यदि आप उदाहरण के लिए Ideone का उपयोग करते हैं , जो डिफ़ॉल्ट रूप से पुराने संकलक का उपयोग करता है, तो आप 1200 से अधिक forलूप आसानी से प्राप्त कर सकते हैं।

लूप के लिए यह बहुत बुरा डिजाइन का एक संकेतक है, हालांकि। मुझे उम्मीद है कि यह सवाल पूरी तरह से काल्पनिक है।


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

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

1
आओ, भाषा में ही कोई सीमा नहीं है। फ़ाइल सिस्टम सिर्फ 20MB का है और स्रोत फ़ाइल या निष्पादन योग्य बहुत बड़ा हो रहा है एक वास्तविक सीमा नहीं है @ Marco13
पैट्रिक हॉफमैन

3
आपके उत्तर के विपरीत, प्रत्येक लूप वास्तव में उपयोग किए गए स्टैक स्थान में जोड़ता है। (यह एक नया चर जोड़ रहा है।) इसलिए जब आपके पास पर्याप्त चर होंगे तो ढेर बाहर निकल जाएगा। यह ठीक वैसा ही मुद्दा है जैसा कि पुनरावृत्ति (सिवाय इसके कि एक विधि के लिए स्टैक फ्रेम केवल एक से अधिक स्टैक स्पेस लेने के लिए जा रहा है int)। यदि वे बिना लूप चर के साथ लूप थे, तो यह अलग होगा।
सेवक

3
मेरा मानना ​​है कि सीपीथॉन भाषा निर्माण के घोंसले के शिकार के बारे में 50 पर सीमित करता है। यहां तक ​​कि 1200 नेस्टेड छोरों का समर्थन करने का कोई मतलब नहीं है ... पहले से ही 10 स्पष्ट संकेत हैं कि कार्यक्रम में कुछ गलत है।
बकुरीउ

13

MSIL के लिए सभी C # संकलित करने की सीमा है। MSIL केवल 65535 स्थानीय चर का समर्थन कर सकता है। अगर आपकाfor लूप्स आपके द्वारा दिखाए गए उदाहरण के समान हैं, तो प्रत्येक को एक चर की आवश्यकता होती है।

यह संभव है कि आपका कंपाइलर इस सीमा को दरकिनार करते हुए स्थानीय चर के लिए भंडारण के रूप में कार्य करने के लिए वस्तुओं को आवंटित कर सके। हालाँकि, मुझे यकीन नहीं है कि इससे किस प्रकार के विषम परिणाम आएंगे। ऐसे मुद्दे हो सकते हैं जो प्रतिबिंब के साथ उत्पन्न होते हैं जो इस तरह के दृष्टिकोण को अवैध बनाते हैं।


6
लूप के लिए आपको किसी चर की जरूरत नहीं है।
पैट्रिक हॉफमैन

1
@PatrickHofman आप सही हैं, मैंने उस हिस्से को संपादित किया जिसे मैं शामिल करना भूल गया था
Cort Ammon

@PatrickHofman अगर मैं बिना चरों के लिए गलत नहीं हूँ, तो यह चर के बराबर है while(true)जो एक अनंत लूप का निर्माण करेगा। यदि हमने इस प्रश्न को संपादित किया कि "क्या किसी समाप्ति कार्यक्रम में लूप्स के लिए नेस्टेड की संख्या की सीमा है?" तो क्या हम एक कठिन सीमा बनाने के लिए स्थानीय चर चाल का उपयोग कर सकते हैं?
एमोरी

2
@emory कुछ भी नहीं वास्तव में बेतुका छोरों से रोकता है जो चर का पुन: उपयोग करते हैं। मैं उन्हें छोरों के लिए सार्थक नहीं कहूंगा, लेकिन वे किया जा सकता है।
Cort Ammon

1
@ आप एक लूप को समाप्त कर सकते हैं breakया लूप की स्थिति को कुछ बाहरी जाँच सकते हैं, जैसे( ; DateTime.now() < ... ; )
ग्रिशा लेविट

7

खाली के लिए 800 और 900 के बीच for(;;) छोरों के ।

छोड़कर मार्को 13 के दृष्टिकोण को देखा, कोशिश की for(;;) छोरों :

for (;;)  // 0
for (;;)  // 1
for (;;)  // 2
// ...
for (;;)  // n_max
{
  // empty body
}

इसने 800 नेस्टेड के लिए काम किया for(;;), लेकिन इसने एक ही त्रुटि दी जिसे 900 लूप्स की कोशिश करते समय मार्को 13 का सामना करना पड़ा।

जब यह संकलन करता है, for(;;)तो सीपीयू को अधिकतम किए बिना थ्रेड को ब्लॉक करने के लिए प्रकट होता है; सतही तौर पर, यह ए की तरह काम करता है Thread.Sleep()


2
"यह बहुत तुरन्त चल रहा है खत्म" - यह अजीब है - मैंने सोचा था कि for(;;)सी # में एक अनंत लूप होगा ?! (मैं इसे अभी बाहर करने की कोशिश नहीं कर सकता, लेकिन अगर यह गलत निकला, तो मैं यह टिप्पणी हटा
दूंगा

@ Marco13: हाँ, तुम सही हो! यह निश्चित नहीं है कि पहले मेरे परीक्षण कोड में क्या हो रहा था, लेकिन for(;;)सीपीयू समय का उपभोग किए बिना अवरुद्ध हो रहा है।
नट

A ((;)) लूप एक अनंत लूप है इसलिए उनमें से (?) लूप या 800 के लिए एक और जोड़ें क्योंकि उन्हें चलाया नहीं जाएगा। पहले वाला हमेशा के लिए चलेगा।
फ्रेड स्मिथ

1
@FredSmith: for(;;)लूप्स नेस्टेड होते हैं, इसलिए वे सभी सबसे नेस्टेड लूप से शुरू होते हैं, जो अनंत है। पहले for(;;)ब्लॉक करने के लिए, यह होना चाहिए for(;;){}। ऐसा क्यों करते हैं, यह देखने के लिए सिर्फ एक परीक्षा थी कि वर्तमान .NET / C # कार्यान्वयन की क्या सीमाएँ हैं; जाहिरा तौर पर यह 900 तक नहीं जा सकता है for(;;), भले ही, जैसा कि आप ध्यान दें, यह कुछ भी नहीं करता है।
नट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.