2009-11-18 3 views
0

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

Благодарим за помощь!

местоположение - это объект, содержащий строку 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. 
    } 
} 
+0

Вы должны повторить это и добавить тег домашней работы, чтобы быть более откровенным. –

+2

В Java принято использовать все имена классов, начинающиеся с символа верхнего класса; «location» больше походил на переменную для меня, чем класс, пока я не ударил по психическому segfault и вернулся, чтобы осмотреть его более внимательно. Никогда не недооценивайте силу конвенции! –

+0

Я не знал, что есть домашняя бирка, и как это полезно для тех, кто пытается ответить на вопрос о программировании? Кроме того, первое предложение в моем вопросе: «Привет, ребята, я работаю над программой для ** университетского курса **» – seventeen

ответ

0

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

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 

Edit: ваш алгоритм, теперь он может достигать только to, если последний шаг диагональ. Если ваш последний шаг горизонтален, вы всегда отклоняетесь вертикально и наоборот, так что вы будете перемещаться вокруг цели ad infinitum, что приведет к переполнению стека. Изначальным решением было бы использовать nextInt (3) и не отклоняться от одной трети времени.

+0

+1 - Упрощение было бы ключевым, но он может захотеть, чтобы все основания были закрыты. Не кажется, что используется Random r, так как to.r отличается от «r». –

+0

Он использует r для создания случайных шагов в 'r.nextInt (2) == 0' – rsp

0

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

+0

да, ошибка, но в этом случае это не помогло бы, метод get_line сверху заполнит любой стек любого размера;) –

+0

В общем, увеличение стека времени выполнения является iffy, поскольку исчерпание часто является признаком бесконечной рекурсии. –

+1

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

2

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

3

что такое условие, что, когда эти два параметра будут верны:

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

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

1

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

0

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

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; 
1

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

Смежные вопросы