stack overflow explanation from code sample - java

I saw this code snippet from my exam, and my first hint would be it will throw StackOverFlowError
for (int i = 10; i > 5; i++) {
if(i == 1000) i = 10;
System.out.println(i);
}
It happens to be that its not. From the code sample, can you please explain why this is not going to throw StackOverFlowError.

To have a StackOverflowError, you have to be adding things to the call stack.
You're adding calls to System.out.println, but they simply don't stack on top of one another, so there would only be one call on the stack at any given time.
Now, an example of StackOverflowError would be recursion that does not sufficiently resolve the previous entries on the call stack; something that simply has too many method calls to itself for a sufficiently large parameter, or creates more calls to itself for every call to itself than it can deal with. (The Ackermann function is a notorious example of this.)
If we define factorial as thus:
public long factorial(long value) {
return value == 0 ? 1 : value * factorial(value - 1);
}
...and give it a sufficiently large value...
System.out.println(factorial(1891279172981L));
...then we won't have enough stack space to handle all 1891279172981 of those entries on to it.

This snippet causes an infinite loop, but not an infinite recursion (since you don't have a method calling itself infinite times). Therefore it will not cause a StackOverflowError.

Related

Java: Recursive sudoku solutions counting algorithm

I made Sudoku checker/solver with ease, but I need one that can tell wheter there is more than one solution, and couldn't wrap my head around it. I found a working algorithm, but I'm trying to understand why it's working. It's the answer from this question, provided by #fabian
Copied below:
// returns 0, 1 or more than 1 depending on whether 0, 1 or more than 1 solutions are found
static byte solve(int i, int j, int[][] cells, byte count /*initailly called with 0*/) {
if (i == 9) {
i = 0;
if (++j == 9)
return 1+count;
}
if (cells[i][j] != 0) // skip filled cells
return solve(i+1,j,cells, count);
// search for 2 solutions instead of 1
// break, if 2 solutions are found
for (int val = 1; val <= 9 && count < 2; ++val) {
if (legal(i,j,val,cells)) {
cells[i][j] = val;
// add additional solutions
count = solve(i+1,j,cells, count));
}
}
cells[i][j] = 0; // reset on backtrack
return count;
}
I tried implementing it, and as it should, it works. However though I think I understand what each part of the code does, I cannot get why it works.
First: The first if statement stops the method once the final number in the 2d array is reached. I get this in finding a single solution, but why does it work in finding more than one solution? Shouldn't the method just return 0+1=1 after solution is found?
Second: after if (cells[i][j] != 0) why does the recursive solve(...) call need return statement in front of it? I have made several recursive algorithms, but always by just calling the method again.
Third: If none suitable numbers are found the for loop stops and 0 is inputted to the cell place. Since it should already have 0, shouldn't the backtracking put 0 to the last place instead of current? At least that is how I made the solver that I made myself.
Fourth: After the backtrack set, there is just return count. Why is the program still working? Shouldn't it just return count = 0 and stop after facing first place that doesn't allow any numbers? Howcome there isn't a recursive call at the end?
If you made it this far on this rampling question, it is clear that I'm understanding some things completely wrong. I'd highly appreciate assistance/explanation, since using code one doesn't understand is a complete failure as far as learning to code goes.
Ok, so Google gracefully provided an Powerpoint lecture from Harvard:
http://www.fas.harvard.edu/~cscie119/lectures/recursion.pdf
If someone else is having problems getting recursive backtracking, I recommend checking it out. Very short but informative.
My problem seemed to be only that I stupidly (at least on hindsight) assumed for the method to stop after it calls itself recursively. I forgot that after it gets results from the recursive call it makes, it executes itself to the end. Funny how you can use umphteen hours solving something just because your initial thought process was flawed. Well, live and learn I guess.

How to avoid StackOverflowError for a recursive function

I'm writing a function that will call itself up to about 5000 times. Ofcourse, I get a StackOverflowError. Is there any way that I can rewrite this code in a fairly simple way?:
void checkBlocks(Block b, int amm) {
//Stuff that might issue a return call
Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
if (condition)
checkBlocks(blockDown, amm);
Block blockUp = (Block) b.getRelative(BlockFace.UP);
if (condition)
checkBlocks(blockUp, amm);
//Same code 4 more times for each side
}
By the way, what is the limitation of how deep we may call the functions?
Use an explicit stack of objects and a loop, rather than the call stack and recursion:
void checkBlocks(Block b, int amm) {
Stack<Block> blocks = new Stack<Block>();
blocks.push(b);
while (!blocks.isEmpty()) {
b = blocks.pop();
Block blockDown = (Block) b.getRelative(BlockFace.DOWN);
if (condition)
blocks.push(block);
Block blockUp = (Block) b.getRelative(BlockFace.UP);
if (condition)
blocks.push(block);
}
}
default stack size in java is 512kb. if you exceed that program will terminate throwing StackOverflowException
you can increase the stack size by passing a JVM argument :
-Xss1024k
now stack size is 1024kb. you may give higher value based on your environment
I don't think we can programmatically change this
You can increase the stack size by using -Xss4m.
You may put your "Block"s into a queue/stack and iterate as long as Blocks are available.
It's obvious that you get StackOverflow with such branching factor of your recursion. In other languages it can be achieved by Tail Call Optimization. But I suppose your problem needs another way to solve.
Ideally, you perform some check on Block. Maybe you can obtain list of all blocks and check each of them iteratively?
In most cases recursion is used in a wrong way. You shouldn't get a stack over flow exception.
Your method has no return type/value.
How do you ensure your initial Block b is valid?
If you are using recursion, answer yourself the following question:
what is my recursion anchor (when do i stop with recursion)
what is my recursion step (how do I reduce my number of calculations)
Example:
n! => n*n-1!
my recursion anchor is n == 2 (result is 2), so I can calculate all results beginnging from this anchor.
my recursion step is n-1 (so each step I get closer to the solution (and in this fact to my recursion anchor))

Simple loop performance issue

Say I have a simple PHP loop like this one
// Bad example
$array = array('apple','banana','cucumber');
for ($i = 1; $i < count($array); $i++) {
echo $array[$i];
}
I know this is a bad practice. It's better not using count() inside a loop.
// Nice example
$array = array('apple','banana','cucumber');
$limit = count($array);
for ($i = 1; $i < $limit; $i++) {
// do something...
}
In Java, I would do it this way
// Bad example?
String[] array = {"apple","banana","cucumber"};
for(int i = 0; i < array.length; i++){
System.out.println(array[i]);
}
Question: Isn't this above a bad practice too? Or it is just the same as the example below?
// Nice example?
String[] array = {"apple","banana","cucumber"};
int limit = array.length;
for(int i = 0; i < limit; i++){
System.out.println(array[i]);
}
Any decent compiler/interpreter should automatically optimise the first example to match the second (semantically speaking anyway, if not exactly literally), and probably the third to match the fourth. It's known as a loop invariant optimisation, where the compiler recognises that an entity (variable, expression, etc) does not vary within the loop (i.e. is invariant) and removes it to outside the loop (loosely speaking).
It's not bad practice at all anymore, if it ever was.
The "bad" examples you use are not equivalent, and thus are not comparable - even if they seem so on the surface. Using this description:
for (initialization; termination; increment) {
statement(s)
}
(which is descriptive of both PHP and java loops), the initialization statement is executed once, at the start of the loop. The termination statement and the increment are executed for each iteration of the loop.
The reason it is bad practice to use PHP's count in the termination statement is that, for each iteration, the count function call occurs. In your Java example, array.length is not a function call but a reference to a public member. Therefore, the termination statements used in your examples are not equivalent behavior. We expect a function call to be more costly than a property reference.
It is bad practice to place a function call (or call a property that masks a function) in the termination statement of a for loop in any language which has the described loop mechanics. That's what makes the PHP example "bad", and it would be equally bad if you used a count-type function in Java for loop's termination statement. The real question, then, is whether Java's Array.length does indeed mask a function call - the answer to that is "no" (see the potential duplicate question, and/or check out http://leepoint.net/notes-java/data/arrays/arrays.html)
The main difference is that count() is a function whereas array.length is a property and therefore not different from a limit variable.
They are not the same, in the Java "nice example" you are not calculating the length of the array every time. Instead, you are storing that in the limit variable and using that to stop the calculation instead of the result of calling the length function on the array every iteration through the for loop.
EDIT: Both of the things that you thought were "bad practice" are bad practice and the "nice examples" are the more efficient ways (at least in theory). But it is true that in implementation there will not be any noticeable difference.
In java this doesn't matter an array has this attribute as a constant (public final int).
The difference is in java arrays have a fixed size and can not grow so there would be no need to count the elements every time to access length.

Stack Overflow Error java

I'm trying to solve a problem that calls for recursive backtracking and my solution produces a stackoverflow error. I understand that this error often indicates a bad termination condition, but my ternimation condition appears correct. Is there anything other than a bad termination condition that would be likely to cause a stackoverflow error? How can I figure out what the problem is?
EDIT: sorry tried to post the code but its too ugly..
As #irreputable says, even if your code has a correct termination condition, it could be that the problem is simply too big for the stack (so that the stack is exhausted before the condition is reached). There is also a third possibility: that your recursion has entered into a loop. For example, in a depth-first search through a graph, if you forget to mark nodes as visited, you'll end up going in circles, revisiting nodes that you have already seen.
How can you determine which of these three situations you are in? Try to make a way to describe the "location" of each recursive call (this will typically involve the function parameters). For instance, if you are writing a graph algorithm where a function calls itself on neighbouring nodes, then the node name or node index is a good description of where the recursive function is. In the top of the recursive function, you can print the description, and then you'll see what the function does, and perhaps you can tell whether it does the right thing or not, or whether it goes in circles. You can also store the descriptions in a HashMap in order to detect whether you have entered a circle.
Instead of using recursion, you could always have a loop which uses a stack. E.g. instead of (pseudo-code):
function sum(n){
if n == 0, return 0
return n + sum(n-1)
}
Use:
function sum(n){
Stack stack
while(n > 0){
stack.push(n)
n--
}
localSum = 0
while(stack not empty){
localSum += stack.pop()
}
return localSum
}
In a nutshell, simulate recursion by saving the state in a local stack.
You can use the -Xss option to give your stack more memory if your problem is too large to fix in the default stack limit size.
As the other fellas already mentioned, there might be few reasons for that:
Your code has problem by nature or in the logic of the recursion. It has to be a stoping condition, base case or termination point for any recursive function.
Your memory is too small to keep the number of recursive calls into the stack. Big Fibonacci numbers might be good example here. Just FYI Fibonacci is as follows (sometimes starts at zero):
1,1,2,3,5,8,13,...
Fn = Fn-1 + Fn-2
F0 = 1, F1 = 1, n>=2
If your code is correct, then the stack is simply too small for your problem. We don't have real Turing machines.
There are two common coding errors that could cause your program to get into an infinite loop (and therefore cause a stack overflow):
Bad termination condition
Bad recursion call
Example:
public static int factorial( int n ){
if( n < n ) // Bad termination condition
return 1;
else
return n*factorial(n+1); // Bad recursion call
}
Otherwise, your program could just be functioning properly and the stack is too small.

How can I refactor a large block of if statements in Java?

I recently profiled some code using JVisualVM, and found that one particular method was taking up a lot of execution time, both from being called often and from having a slow execution time. The method is made up of a large block of if statements, like so: (in the actual method there are about 30 of these)
EcState c = candidate;
if (waypoints.size() > 0)
{
EcState state = defaultDestination();
for (EcState s : waypoints)
{
state.union(s);
}
state.union(this);
return state.isSatisfied(candidate);
}
if (c.var1 < var1)
return false;
if (c.var2 < var2)
return false;
if (c.var3 < var3)
return false;
if (c.var4 < var4)
return false;
if ((!c.var5) & var5)
return false;
if ((!c.var6) & var6)
return false;
if ((!c.var7) & var7)
return false;
if ((!c.var8) & var8)
return false;
if ((!c.var9) & var9)
return false;
return true;
Is there a better way to write these if statements, or should I look elsewhere to improve efficiency?
EDIT: The program uses evolutionary science to develop paths to a given outcome. Specifically, build orders for Starcraft II. This method checks to see if a particular evolution satisfies the conditions of the given outcome.
First, you are using & instead of &&, so you're not taking advantage of short circuit evaluation. That is, the & operator is going to require that both conditions of both sides of the & be evaluated. If you are genuinely doing a bitwise AND operation, then this wouldn't apply, but if not, see below.
Assuming you return true if the conditions aren't met, you could rewrite it like this (I changed & to &&).
return
!(c.var1 < var1 ||
c.var2 < var2 ||
c.var3 < var3 ||
c.var4 < var4 ||
((!c.var5) && var5) ||
((!c.var6) && var6) ||
((!c.var7) && var7) ||
((!c.var8) && var8) ||
((!c.var9) && var9));
Secondly, you want to try to move the conditions that will most likely be true to the top of the expression chain, that way, it saves evaluating the remaining expressions. For example, if (c1.var4 < var4) is likely to be true 99% of the time, you could move that to the top.
Short of that, it seems a bit odd that you'd be getting a significant amount of time spent in this method unless these conditions hit a database or something like that.
First, try rewriting the sequence of if statements into one statement (per #dcp's answer).
If that doesn't make much difference, then the bottleneck might be the waypoints code. Some possibilities are:
You are using some collection type for which waypoints.size() is expensive.
waypoints.size() is a large number
defaultDestination() is expensive
state.union(...) is expensive
state.isSatisfied(...) is expensive
One quick-and-dirty way to investigate this is to move all of that code into a separate method and see if the profiler tells you it is a bottleneck.
If that's not the problem then your problem is intractable, and the only way around it would be to find some clever way to avoid having to do so many tests.
Rearranging the test order might help, if there is an order that is likely to return false more quickly.
If there is a significant chance that this and c are the same object, then an initial test of this == c may help.
If all of your EcState objects are compared repeatedly and they are immutable, then you could potentially implement hashCode to cache its return value, and use hashCode to speed up the equality testing. (This is a long shot ... lots of things have to be "right" for this to help.)
Maybe you could use hashCode equality as a proxy for equality ...
As always, the best thing to do is measure it yourself. You can instrument this code with calls to System.nanotime() to get very fine-grained durations. Get the starting time, and then compute how long various big chunks of your method actually take. Take the chunk that's the slowest and then put more nanotime() calls in it. Let us know what you find, too, that will be helpful to other folks reading your question.
So here's my seat of the pants guess ...
Optimizing the if statements will have nearly no measurable effect: these comparisons are all quite fast.
So let's assume the problem is in here:
if (waypoints.size() > 0)
{
EcState state = defaultDestination();
for (EcState s : waypoints)
{
state.union(s);
}
state.union(this);
return state.isSatisfied(candidate);
}
I'm guessing waypoints is a List and that you haven't overridden the size() method. In this case, List.size() is just accessing an instance variable. So don't worry about the if statement.
The for statement iterates over your List's elements quite quickly, so the for itself isn't it, though the problem could well be the code it executes. Assignments and returns take no time.
This leaves the following potential hot spots:
The one call to defaultDestination().
All the calls to EcState.union().
The one call to EcState.isSatisfied().
I'd be willing to bet your hotspot is in union(), especially since it's building up some sort of larger and larger collection of waypoints.
Measure with nanotime() first though.
You aren't going to find too many ways to actually speed that up. The two main ones would be taking advantage of short-circuit evaluation, as has already been said, by switching & to &&, and also making sure that the order of the conditions is efficient. For example, if there's one condition that throws away 90% of the possibilities, put that one condition first in the method.

Categories