Runtime exception, recursion too deep

后端 未结 12 931
余生分开走
余生分开走 2020-12-19 04:59

I converted the pseudo-code here into C#, and have it recursively repeat 10,000 times. But I get a C# runtime error, StackOverflow Exception after 9217

相关标签:
12条回答
  • 2020-12-19 05:28

    Don't use recursion. This is a good sample case of when you should not recurse, as you will cause a call stack overflow.

    You can probably convert that to non-recursive easily.

    0 讨论(0)
  • 2020-12-19 05:28

    You cannot prevent it, the function calls itself too many times; there's a limit on how deep the call stack can get, and your function reaches it.

    0 讨论(0)
  • 2020-12-19 05:31

    To glom onto what everyone else is saying here-- this is a Stack Overflow (woot! a Stack Overflow question question on StackOverflow. This might cause a stack . . .)

    Anyway, each time your recursive method is called, it pushes the stack, which is to say that it puts a reference to itself onto the stack, so that when the last call to CalculatePi is called, it can unwind all of the rest of the calls.

    The stack is not an infinite resource. Each push to the stack eats up a bit of memory, and when you use it all up, you get a stack overflow.

    0 讨论(0)
  • 2020-12-19 05:31

    The recursive call is not tail-recursive, and even if it were, it wouldn't help since the C# compiler does not currently optimize tail-recursive calls. EDIT: As pointed out by Eric Lippert and Gabe, the CLR could choose to generate tail calls even when explicit tail-call instructions are not in the emitted IL.

    1. The best way would be to turn this recursive solution into an iterative one.
    2. Since it almost completes, a quick hack might be to increase the stack-size of the thread on which this method runs.

    Please don't do this. For fun only:

    static void Main()
    {
        Console.WriteLine(SafeCalculatePi(10000));
    }
    
    // Calculates PI on a separate thread with enough stack-space 
    // to complete the computation
    public static double SafeCalculatePi(int maxRecursion)
    {
        // We 'know' that you can reach a depth of 9217 for a 1MB stack.
        // This lets us calculate the required stack-size, with a safety factor
        double requiredStackSize = (maxRecursion / 9217D) * 1.5 * 1024 * 1024 ; 
    
        double pi = 0;
        ThreadStart ts = delegate { pi = CalculatePi(maxRecursion); };
        Thread t = new Thread(ts, (int)requiredStackSize);
        t.Start();
        t.Join();
        return pi;
    }
    
    0 讨论(0)
  • 2020-12-19 05:35

    Recursive function calls are almost always a really awful way to do things.

    I would simply get the value of pi from a header file/math library.

    0 讨论(0)
  • 2020-12-19 05:45

    It's not infinite recursion obviously since it stops after 10,000 levels, but it's still not the best idea.

    Ten thousand stack levels is an awful lot - the stack is not a massive resource. You should convert it into an iterative solution.

    0 讨论(0)
提交回复
热议问题