简体   繁体   中英

Recursive calls causes Java Stack Overflow

Problem

Hello,

I'm doing Java project for my university studies and encountered a problem I could not solve myself, this is the first time I'm askin a question here so tell me if I did anything wrong.

I am trying to solve a simply connected maze using a Wall follower algorithm, the algorithm walks the maze and always trys to turn right then move forward and lastly turns right. Whe encountering a dead the algorithm it will turn around and start moving back.

My recursive soution causes a StackOverflow error when the maze size is above 500 x 500. I am wondering is there a error in the code or is it just not viable to solve this kind of problem with recursive algorithm.

NOTE: The problem is not that the algorithm does not work but that it runs out of Stack!

** Question **

Is there a loop or memory leak or is it just not possible to use recursion after a certain number of calls.

I have a iterative solution that works at any maze size.

Project repository

Program

the Maze is represented as a 2D-array and each square has its own class that holds it coordinates inside the maze. My thinking is that Java stores these Square objects without cleaning them while the recursive method is running. The move() method calls a method getSquareInDirection that creates a new Square object, that might cause the error. The other methods only alter the enum Dircetion and should not be the cause of the error, but I am not sure of this.

Parent method

    public SquareQue solveRecursive() {
        Square start = maze.getStart();
        SquareQue path = new SquareQue();
        move(start, Direction.DOWN, path);

        maze.setSquareValue(start.getWidth(), start.getHeight(), 3);

        return path;
    }

Recursive method

public SquareQue move(Square pos, Direction dir, SquareQue path) {
        if (maze.reachedFinish(pos)) {
            path.add(pos);
            return path;
        }

        if (canMove(pos, getDirectionToRight(dir))) {
            pos = getSquareInDirection(pos, getDirectionToRight(dir));
            path.add(pos);
            return move(pos, getDirectionToRight(dir), path);

        } else if (canMove(pos, dir)) {
            pos = getSquareInDirection(pos, dir);
            path.add(pos);
            return move(pos, dir, path);

        } else if (canMove(pos, getDirectionToLeft(dir))) {
            pos = getSquareInDirection(pos, getDirectionToLeft(dir));
            path.add(pos);
            return move(pos, getDirectionToLeft(dir), path);

        } else {
            pos = getSquareInDirection(pos, reverse(dir));
            return move(pos, reverse(dir), path);
        }
    }

Recrsuvie method calls this

public static Square getSquareInDirection(Square pos, Direction dir) {
        int col = pos.getWidth();
        int row = pos.getHeight();
        if (dir == Direction.UP) {
            return new Square(col, row - 1);
        }
        if (dir == Direction.DOWN) {
            return new Square(col, row + 1);
        }
        if (dir == Direction.RIGHT) {
            return new Square(col + 1, row);
        }
        if (dir == Direction.LEFT) {
            return new Square(col - 1, row);
        }
        return null;
    }

Reproduce error

Easiest way to reproduce the error is to clone the project and edit the GUI class.

Inside GUI class inside the method getSolveScene and alter the button settings for calling a large recursive result method:

if (selectedString.equals("Large")) {
                    stage.setScene(getSolveScene(81, 81, 12, setting));
                    stage.setTitle("Maze generator - Recursive Large");

                }

Repalce the getSolveScene with for example: (getSolveScene(501, 501, 12, setting) .

After this you can save and run the progra with settings Large and Recursive.

Thanks in advance for responding!

Recursive approach should work as long as your stack size is large enough to accomodate the required depth of recursion (that depends on the size of your maze).

However, I also see another problem - getSquareInDirection doesn't seem to be checking not to go back to the path that was already visited. If that happens, your program might get stuck in a "loop" aka infinite recursion. Try printing current coordinates in move and see if they repeat themselves. (Hint: they should not)

The default stack size is quite small (at least often too small for recursive algorithms). Default is in most VMs only 1MByte.

To change the stack size use the VM-parameter: -Xss

But to check if the stack size is your only problem, try to solve a smaller maze first.

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