your programing

중첩 된 'for'루프의 수에 제한이 있습니까?

lovepro 2020. 10. 9. 11:33
반응형

중첩 된 'for'루프의 수에 제한이 있습니까?


모든 것에 제한이 있기 때문에 중첩 for루프 수에 제한이 있는지 또는 메모리가있는 한 추가 할 수 있는지 궁금합니다 . Visual Studio 컴파일러가 이러한 프로그램을 만들 수 있습니까?

물론 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....
      }
    }
  }
}

나는 이것을 게시하여 팔다리로 나가고 있지만 대답은 다음과 같다고 생각합니다.

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.CSharpSimplifyTypeNamesDiagnosticAnalyzer'에서 '프로그램을 안전하게 계속 실행하기위한 스택 부족'메시지와 함께 'System.InsufficientExecutionStackException'유형의 예외가 발생했습니다. 이것은 호출 스택에 너무 많은 함수를 가지고 있거나 너무 많은 스택 공간을 사용하는 스택에 함수를 가지고 있기 때문에 발생할 수 있습니다. '.

기본 컴파일러 메시지

오류 CS8078 :식이 너무 길거나 복잡하여 컴파일 할 수 없습니다.

물론 이것은 순전히 가설적인 결과입니다. 가장 안쪽의 루프가 하나 이상의 작업을 수행하는 Console.WriteLine경우 스택 크기를 초과하기 전에 더 적은 수의 중첩 루프가 가능할 수 있습니다. 또한 이는 오류 메시지에 언급 된 "분석기"의 최대 스택 크기를 늘리거나 결과 실행 파일에 대해 (필요한 경우) 숨겨진 설정이있을 수 있다는 점에서 엄격한 기술 제한이 아닐 수도 있습니다. 그러나 대답의이 부분은 C #을 깊이 알고있는 사람들에게 맡겨져 있습니다.


최신 정보

댓글질문에 대한 답변 :

이 답변이 확장 되어 for 루프에서 사용 되지 않는 경우 스택에 575 개의 로컬 변수를 넣을 수 있는지 여부 및 / 또는 575 개의 비 중첩 for 루프를 넣을 수 있는지 여부를 실험적으로 "증명"하는 것을보고 싶습니다 . 단일 기능

두 경우 모두 대답은 다음과 같습니다. 예, 가능합니다. 575 개의 자동 생성 문으로 메서드를 채울 때

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

여전히 컴파일 할 수 있습니다. 다른 모든 것이 나를 놀라게 할 것입니다. int변수에 필요한 스택 크기는 2.3KB에 불과합니다. 하지만 궁금해서 더 많은 한계를 테스트하기 위해이 숫자를 늘 렸습니다. 결국 컴파일 되지 않아 오류가 발생했습니다.

오류 CS0204 : 컴파일러에 의해 생성 된 로컬을 포함하여 65534 로컬 만 허용됩니다.

which is an interesting point, but has already been observed elsewhere: Maximum number of variables in method

Similarly, 575 non-nested for-loops, as in

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);
}

can be compiled as well. Here, I also tried to find the limit, and created more of these loops. Particularly, I wasn't sure whether the loop variables in this case also count als "locals", because they are in their own { block }. But still, more than 65534 is not possible. Finally, I added a test consisting of 40000 loops of the pattern

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

that contained an additional variable in the loop, but these seem to count as "locals" as well, and it was not possible to compile this.


So to summarize: The limit of ~550 is indeed caused by the nesting depth of the loops. This also was indicated by the error message

error CS8078: An expression is too long or complex to compile

The documentation of error CS1647 unfortunately (but understandably) does not specify a "measurement" of complexity, but only gives the pragmatic advice

There was a stack overflow in the compiler processing your code. To resolve this error, simplify your code.

To emphasize this again: For the particular case of deeply nested for-loops, all this is rather academic and hypothetical. But websearching for the error message of CS1647 reveals several cases where this error appeared for code that was most likely not intentionally complex, but created in realistic scenarios.


There is no hard limit in the C# language specification or the CLR. Your code would be iterative, rather than recursive, which could lead to a stack overflow quite fast.

There are a few things that could count as a threshold, for example the (generally) int counter you would use, which would allocate an int in memory for each loop (and before you have allocated your entire stack with ints...). Note that the use of that int is required and you may reuse the same variable.

As pointed out by Marco, the current threshold is more in the compiler than in the actual language specification or runtime. Once that is recoded, you might up with quite some more iterations. If you for example use Ideone, which by default uses the old compiler, you can get over 1200 for loops easily.

That much for loops are an indicator of bad design though. I hope this question is purely hypothetical.


There is a limit for all C# compiled down to MSIL. MSIL can only support 65535 local variables. If your for loops are like the ones you showed in the example, each one requires a variable.

It's possible that your compiler could allocate objects on the heap to act as storage for local variables, circumventing this limit. However, I'm not sure what sorts of odd results would come from that. There may be issues that arise with reflection which make such an approach illegal.


Between 800 and 900 for empty for(;;) loops.

Mirrored Marco13's approach, except tried for(;;) loops:

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

It worked for 800 nested for(;;), but it gave the same error that Marco13 encountered when trying 900 loops.

When it does compile, the for(;;) appears to block the thread without maxing out the CPU; superficially, it seems to act like a Thread.Sleep().

참고URL : https://stackoverflow.com/questions/41347019/is-there-a-limit-to-the-number-of-nested-for-loops

반응형