Why doesn't this recursion produce a StackOver

2019-04-21 14:25发布

问题:

What is wrong with this code:

using System;
namespace app1
{
    static class Program
    {
        static int x = 0;
        static void Main()
        {
            fn1();
        }
        static void fn1()
        {
            Console.WriteLine(x++);
            fn1();
        }
    }
}

I compile this piece of code using this command:

csc /warn:0 /out:app4noex.exe app4.cs

When I double click on the exe, it doesn't seem to throw the exception (StackOverFlowException), and keep running forever.

Using visual studio command prompt 2010, but I also have vs 2012 installed on the system, all up to date.

回答1:

Because the optimizer unrolls the tail recursion call into:

    static void fn1()
    {
      START:

        Console.WriteLine(x++);
        GOTO START;
    }

Rewrite to get exceptions like so:

   static int y;

   static void fn1()
   {
       Console.WriteLine(x++);
       fn1();
       Console.WriteLine(y++);
   }


回答2:

The x64 jitter is detecting this as a tail call and optimizing it away while the x86 jitter does not do this. The x64 jitter is more aggressive about these optmizations. See Bart de Smet's analysis and the CLR team's blog post on it.



回答3:

There is such a thing called tail recursive optimization.

From a stack perspective, basically it means that if the last thing an method does is call another method, the new call can take the stack frame of the calling method. For example in:

static void Main()
{
  fn(0);
}

static void fn(int value)
{
   fn(value+1);
}

instead of the call stack growing Main->fn(0)->fn(1)->... ad nauseam, it will be at exactly two links long, first Main->fn(0) than Main->fn(1), up to Main->fn(int.MaxValue) where it will either blow up or overflow.

Now, the question is, does the C# compiler actually does this?
AFAIK, using the 4.0 and later C# compilers, when compiling in a x86 environment, it does not use tail-call optimization, and when compiling x64 application, it does use tail-call optimization (and apparently, from the other comments/answers I'm correct). E.g. On my system, using LINQPad, the code you provided promptly blew up with a StackOverflowException.



回答4:

When program runs in visual studio environment , it will uses a limited stack deep. I mean that when you compile a program in VS2012 by hitting F5 and F6 on keyboard, it will send some parameters to csc.exe program to limit the program and cause the stack-over-flow to aware you of bug that is into your program source code & algorithm. In reality , there is no Stack-over-flow error, program's process will use real storage and virtual storage and OS will done it for you.

Note : it is also related to your os , some os will throw an error if they are weakness on memory management and cpu scheduling .