ошибка переполнения стека Java - PullRequest
0 голосов
/ 18 ноября 2009

Эй, ребята, я работаю над программой для университетского курса, в которой используется метод get_line () для рекурсивного вычисления списка последовательных местоположений для перехода из одной точки на сетке в другую. Когда я запускаю его, я получаю переполнение стека в строке последнего оператора return в методе. Мне было интересно, смогу ли я кому-нибудь еще взглянуть на метод и посмотреть, выглядит ли что-то совершенно неправильно. метод приведен ниже:

Спасибо за помощь!

location - это объект, содержащий строку r и столбец c.

private Vector<location> get_line(location from, location to) {
    location nextLoc = new location();
    Vector<location> loc = new Vector<location>();
    Random r = new Random();

    if(to.r == from.r && to.c == from.c) {
        return(loc);
    } else {
        if(to.r > from.r && to.c > from.c) {
            nextLoc.r = from.r + 1;
            nextLoc.c = from.c + 1;
        } else if(to.r < from.r && to.c < from.c) {
            nextLoc.r = from.r - 1;
            nextLoc.c = from.c - 1;
        } else if(to.r < from.r && to.c > from.c) {
            nextLoc.r = from.r - 1;
            nextLoc.c = from.c + 1;
        } else if(to.r > from.r && to.c < from.c) {
            nextLoc.r = from.r + 1;
            nextLoc.c = from.c - 1;
        } else if(to.r == from.r && to.c > from.c) {
            if(r.nextInt(2) == 0) {
                nextLoc.r = from.r + 1;
            } else {
                nextLoc.r = from.r - 1;
            }
            nextLoc.c = from.c + 1;
        } else if(to.r == from.r && to.c < from.c) {
            if(r.nextInt(2) == 0) {
                nextLoc.r = from.r + 1;
            } else {
                nextLoc.r = from.r - 1;
            }
            nextLoc.c = from.c - 1;
        } else if(to.r < from.r && to.c == from.c) {
            nextLoc.r = from.r - 1;
            if(r.nextInt(2) == 0) {
                nextLoc.c = from.c + 1;
            } else {
                nextLoc.c = from.c - 1;
            }
        } else if(to.r > from.r && to.c == from.c) {
            nextLoc.r = from.r + 1;
            if(r.nextInt(2) == 0) {
                nextLoc.c = from.c + 1;
            } else {
                nextLoc.c = from.c - 1;
            }
        }

        loc.add(nextLoc);

        return(get_line(nextLoc,to)); //stack overflow error occurs here.
    }
}

Ответы [ 7 ]

3 голосов
/ 18 ноября 2009

При каких условиях эти два параметра будут истинны:

if(to.r == from.r && to.c == from.c)

В моем просмотре видно, что nextloc всегда изменяется, поэтому приведенное выше утверждение никогда не будет верным.

2 голосов
/ 18 ноября 2009

"to.r == from.r && to.c == from.c" никогда не оценивается как true ...

1 голос
/ 18 ноября 2009

У вас есть рекурсивная функция здесь. Это функция, которая вызывает себя. Каждый раз, когда вы делаете вызов метода, вы добавляете фрейм в стек. Если ваша рекурсивная функция не завершается в разумном количестве рекурсий, вам не хватит места в стеке. Таким образом, переполнение стека. Как уже говорили другие, похоже, что одно из ваших условий всегда ложно, поэтому вы будете бесконечно повторяться (то есть до тех пор, пока не закончится место в стеке). Это похоже на бесконечный цикл, за исключением того, что аппаратное обеспечение не может справиться с ним, поэтому он падает, а не работает вечно.

1 голос
/ 18 ноября 2009

Если вы получаете переполнение стека, у вас, вероятно, бесконечный цикл. Другими словами, ваш алгоритм никогда не находит точку «до». Попробуйте распечатать значение «nextLoc» в начале метода, чтобы увидеть, добивается ли он какого-либо прогресса в достижении соответствия. Затем вы можете попытаться выяснить, где ваш алгоритм не сработал.

0 голосов
/ 18 ноября 2009

Во-первых, вы запускаете генератор случайных чисел каждый раз, когда вводите метод, двигайтесь:

Random r = new Random();

к атрибуту класса.

Во-вторых, похоже, что если ваш метод вернется, он вернет только пустой вектор, потому что вы каждый раз создаете новый.

В-третьих, вы перечислите 8 возможных направлений, которые делают код более сложным, чем нужно, попробуйте переписать его, обрабатывая строки и столбцы по отдельности, например:

if (to.c == from.c && to.r == from.r) {
    // reached destination
    return;
}

if (to.c > from.c) {
    // move right
} else if (to.c < from.c) {
    // move left
} else {
    // random step left/right
}

if (to.r > from.r) {
    // move down
} else if (to.r < from.r) {
    // move up
} else {
    // random step up/down
}

// take next step

Редактировать : ваш алгоритм в его нынешнем виде может достичь местоположения to, только если последний шаг является диагональным. Если ваш последний шаг горизонтальный, вы всегда отклоняетесь от вертикали и наоборот, поэтому вы будете парить вокруг конечного пункта до бесконечности, что приведет к переполнению стека. Возможным решением было бы использовать nextInt (3), а не отклоняться от одной трети времени.

0 голосов
/ 18 ноября 2009

Вы можете увидеть проблему легче, если упростите свой код, в нем нет ненужного дублирования. Ваши манипуляции со строками и столбцами могут быть независимыми

    if ( to.r > from.r ){
           nextLoc.r = from.r + 1;
    } else if ( to.r < from.r) {
            nextLoc.r = from.r -1;
    }

    if ( to.c > from.c ){
           nextLoc.c = from.c + 1;
    } else if ( to.c < from.c) {
            nextLoc.c = from.c -1;
    }

Мне легче понять, чем твой эквивалент:

    if(to.r > from.r && to.c > from.c) {
        nextLoc.r = from.r + 1;
        nextLoc.c = from.c + 1;
    } else if(to.r < from.r && to.c < from.c) {
        nextLoc.r = from.r - 1;
        nextLoc.c = from.c - 1;
    } else if(to.r < from.r && to.c > from.c) {
        nextLoc.r = from.r - 1;
        nextLoc.c = from.c + 1;
    } else if(to.r > from.r && to.c < from.c) {
        nextLoc.r = from.r + 1;
        nextLoc.c = from.c - 1;
0 голосов
/ 18 ноября 2009

Увеличьте размер стека во время выполнения с помощью -Xss http://forums.sun.com/thread.jspa?threadID=756468

...