简体   繁体   中英

Why does my code cause stack overflow error in java? It should terminate eventually. The for loop version does not cause the error

update 10/23/2014: I thought basically the recursive function is a void function, so no more work needed after the return, it should be equivalent to tail recursive version. And it should not cause the stack overflow. I have actually also tried the tail recursive non-void return type and it still caused the stack overflow error. I guess even though it is tail recursive, it still depends on how compiler interpreter implements it.

The for loop version of the same code does not cause stack overflow error. However the code below (recursive version) does. Essentially they should be doing the same thing. The exception error came up around loop 7000 (i=7000).

I am curious why the recursive version causes the error while the for loop version does not. I have some suspicions but not sure.

//recursive version, overflow

public class Solution {
    int n, low = -1, profit = 0;
    int[] a;

    public int maxProfit(int[] prices) {
        n = prices.length;
        if (n == 0 || n == 1)
            return 0;
        a = prices;
        maxProfit(1);
        return profit;
    }

    public void maxProfit(int i) {

        if (i == n - 1) {
            if (low != -1 && a[i - 1] <= a[i])
                profit += a[i] - low;
            return;
        }
        if (a[i - 1] < a[i] && low == -1) {
            low = a[i - 1];
        }
        if (a[i - 1] > a[i] && low != -1) {
            profit += a[i - 1] - low;
            low = -1;
        }
        //System.out.print(i+",");
        maxProfit(i + 1);
    }

    public static void main(String[] args) {
        Solution sl = new Solution();
        // int[] a = { 1, 9, 6, 9, 1, 7, 1, 1, 5, 9, 9, 9 };
        // int[] a = { 4, 4 };
        // int[] a = { 3, 2 };
        // int[] a = { 1, 2, 3, 4, 3 };
        // int[] a = { 3, 2, 1, 0, 4, 5, 6, 7, 10, 4, 9, 7 };
        int[] a = new int[100001];
        for (int i = 0; i < 100001; i++) {
            a[i] = 100000 - i;
        }
        System.out.println();
        System.out.println(sl.maxProfit(a));
    }
}

Nobody so far has really explained what is happening...

When you call a function it's not simply going there--it has to remember exactly where you were and what all your variables were so it can return to that exact spot when your function returns.

It does this by storing the current state on a stack (An area of memory that builds up in one direction). Every time your app recurses the stack grows deeper needing more memory.

A Stack overflow is when the stack has grown so big that it overflows the memory allocated to it.

your looping version doesn't require any extra memory per iteration because it doesn't have to remember when to go back to--it just runs around in circles and can do so for ever.

Sorry if this wasn't what you were asking.

Your recursion depth is 100000 calls. Yes, with unlimited stack size your stack would not overflow but in practice the stack size is limited. The default stack size on a 32bit VM is 320k and 1024k on a 64 bit vm. On a 32 bit vm your particular function would use 64bits of the stack per each level of the call depth. 32 bits for integer you're passing and 32 bits for the return address. 64bits * 100000 depth = 8 bytes * 100000 depth = 800KB (approx). Which is much larger than the default stack size.

Figured I put an answer in the comments, may as well make it a legit answer...

Recursive functions tend to cause a StackOverflowError when your base case doesn't get hit, making the stack unwind. This can be either from messing up the base case logic, not moving towards the base case, or trying to recurse too deep.

In your case, it's because you're trying to have a call stack 100001 levels deep. That's huge. You're trying to do too much recursively, and that's what's causing the problem.

You are struck because your program has no exit condition.Look it goes into the loop maxProfit(1), but has no option of exiting from the loop.

Update: Once your program gets into this loop there is no way for it to come out..

public void maxProfit(int i) {

    if (i == n - 1) {
        if (low != -1 && a[i - 1] <= a[i])
            profit += a[i] - low;
        System.out.println("i");
        return;
    }
    if (a[i - 1] < a[i] && low == -1) {
        low = a[i - 1];
        System.out.println("i");
    }
    if (a[i - 1] > a[i] && low != -1) {
        profit += a[i - 1] - low;
        low = -1;
        System.out.println("i");
    }
    //System.out.print(i+",");

    maxProfit(i + 1);
 }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM