The following function I wrote causing the program to crash due to the stack overflow, although the recursion is finite.
public static void Key(char[] chars, int i, int l, string str) {
string newStr=null;
for(int j=0; j<l; j++)
newStr+=chars[i/(int)Math.Pow(68, j)%68];
if(newStr==str)
return;
Key(chars, ++i, l, newStr);
}
When I call the method with these parameters, all goes fine:
Key(chars, 0, 4, "aaaa");
But when it comes to bigger number of calls, it throws the StackOverflowException. So I assume the problem is that althogh the method is finite the call stack gets filled up before the the methods' job is done. So I have a few questions about that:
Why the functions don't get clear from the stack, they are no longer needed, they don't return any value.
And if so, is there a way i could clear the stack manually? I tried the
StackTraceclass but it's helpless in this case.
-
4I get the strong impression that you don't understand what the stack is or what it does. Please look into that and your questions should be answered on their own.asawyer– asawyer2013年04月05日 18:46:44 +00:00Commented Apr 5, 2013 at 18:46
-
2Technically your code is tail recursive, if you build this with c# optimizations on you'll never have a stack overflow, you should just get an infinite loop (if your base case is actually never getting hit). Try turning optimizations on and see if you still get a stack overflowdevshorts– devshorts2013年04月05日 18:50:09 +00:00Commented Apr 5, 2013 at 18:50
-
1Maybe you should try to describe what your wanting to accomplish this looks really unnecessarily overly complexMicah Armantrout– Micah Armantrout2013年04月05日 18:55:53 +00:00Commented Apr 5, 2013 at 18:55
-
@Nathan Abramov My suggestion would be to step through your program with the debugger after placing break points and seeing on what iteration it crashes and the conditions therein.Joshua Van Hoesen– Joshua Van Hoesen2013年04月05日 19:05:00 +00:00Commented Apr 5, 2013 at 19:05
4 Answers 4
1) The function clears when it has ended execution. Calling Key inside of itself means that every call to it will be on the stack until the last call ends, at which stage they will all end in reverse order.
2) You can't clear the stack and carry on with the call.
Comments
The stack is still limited. For standard C# applications it is 1 MB. For ASP it is 256 KB. If you need more stack space than that, you'll see the exception.
If you create the thread yourself, you can adjust the stack size using this constructor.
Alternatively, you can rewrite your algorithm so it keeps track of state without using recursion.
1 Comment
It looks like the exit condition of NewStr == Str will never happen and eventually, you will run out of stack.
7 Comments
Math.Pow to compute (chars.Length ^ j) which clearly can produce results you don't expect. Your "I said it is finite" proof is not very convincing so far.Math.Pow produce unexpected results? i will keep increasing by 1 every call, which means all possible choices will be computed.So, regardless of whether your code reaches its base case or not, your code should never get a stack overflow exception in production.
For example, this should give us a stack overflow right?
private static void Main(string[] args)
{
RecursorKey(0);
}
public static int RecursorKey(int val)
{
return RecursorKey(val ++);
}
In fact it doesn't, if you use .NET 4 and are not debugging and your binary is compiled as release.
This is because the clr is smart enough to do what is called tail recursion. Tail recursion isn't applicable everywhere, but in your case it is, and I was easily able to reproduce your exact problem. In your case, each time you call the function it pushes another stack frame onto the stack, so you get the overflow, even though the algorithm would theoretically end at some point.
To solve your issue, here is how you can enable optimizations.
However, I should point out that Jon Skeet recommends to not rely on tail call optimizations. Given that Jon's a smart guy, I'd listen to it him. If your code is going to encounter large stack depths, try rewriting it without recursion.