Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Confusing output from infinite recursion within try-catch

Consider the following code.

public class Action { private static int i=1; public static void main(String[] args) {     try{         System.out.println(i);         i++;         main(args);     }catch (StackOverflowError e){         System.out.println(i);         i++;         main(args);     }  }  } 

I am getting i value up to 4338 correctly. After catching the StackOverflowError output getting wired as follows.

4336 4337 4338 // up to this point out put can understand  433943394339 // 4339 repeating thrice   434043404340 4341 434243424342 434343434343 4344 4345 434643464346 434743474347 4348 434943494349 435043504350 

Consider Live demo here. It is working correctly up to i=4330. Actually how this happen?

FYI:

I did following code to realize what is happening here.

public class Action {      private static int i = 1;     private static BufferedWriter bw;      static {         try {             bw = new BufferedWriter(new FileWriter("D:\\sample.txt"));         } catch (IOException e) {            e.printStackTrace();         }     }      public static void main(String[] args) throws IOException {         bw.append(String.valueOf(i)+" ");         try {             i++;             main(args);         } catch (StackOverflowError e) {             bw.append(String.valueOf(i)+" ");             i++;             main(args);         }     }  } 

Now previous issue not there. now value of i up to 16824744 correct and and runs further. I am hopping this may runs up to value of i=2,147,483,647(max value of int) without an issue.

There is some issue with println(). There are similar answers bellow too. But why?

What will be the actual reason?

like image 413
Ruchira Gayan Ranaweera Avatar asked Aug 19 '13 10:08

Ruchira Gayan Ranaweera


People also ask

How do you stop infinite recursion?

To prevent infinite recursion, you need at least one branch (i.e. of an if/else statement) that does not make a recursive call. Branches without recursive calls are called base cases; branches with recursive calls are called recursive cases. Functions can also be mutually recursive.

Does infinite recursion cause stack overflow?

The most-common cause of stack overflow is excessively deep or infinite recursion, in which a function calls itself so many times that the space needed to store the variables and information associated with each call is more than can fit on the stack.

What is often the cause of infinite recursion?

Most of the time, infinite recursion causes the program to run for a while and then produce a Maximum recursion depth exceeded error. If you suspect that a function is causing an infinite recursion, make sure that there is a base case.

What type of error is infinite recursion?

If a recursion never reaches a base case, it will go on making recursive calls forever and the program will never terminate. This is known as infinite recursion, and it is generally not considered a good idea. In most programming environments, a program with an infinite recursion will not really run forever.


1 Answers

Note the absence of newline characters in 433943394339. It indicates that something wrong happens inside System.out.println().

The essential point here is that System.out.println() requires some stack space to work, so that StackOverflowError is thrown from System.out.println().

Here is your code with marked points:

public static void main(String[] args) {     try{         System.out.println(i); // (1)         i++;         main(args); // (2)     }catch (StackOverflowError e){         System.out.println(i); // (3)         i++;         main(args); // (4)     } } 

Let's imagine what happens at level N of recursion when i = 4338:

  • Statement (1) at level N prints 4338. Output 4338\n
  • i is incremented to 4339
  • Control flow enters level N + 1 at (2)
  • Statement (1) at level N + 1 tries to print 4339, but System.out.println() throws a StackOverflowError before it prints a newline. Output 4339
  • StackOverflowError is caught at level N + 1, statement (3) tries to print 4339 and fails for the same reason again. Output 4339
  • Exception is caught at level N. At this point there is more stack space available, therefore statement (3) tries to print 4339 and succeeds (newline is printed correctly). Output 4339\n
  • i is incremented and control flow enters level N + 1 again at (4)

After this point the situation repeats with 4340.

I'm not sure why some numbers are printed correclty between sequences without newlines, perhaps its related to internal work of System.out.println() and buffers it uses.

like image 148
axtavt Avatar answered Sep 27 '22 16:09

axtavt