Java - ошибка StackOverFlow
Так что благодаря @fireshadow52 мне удалось придумать этот скрипт, который sin
s args[0]
, Тем не менее, он выплевывает StackOverFlow error
, Что это такое, и как (если это возможно) вы их заметите?
class SIN {
public static void main(String[] args) {
double result = sin(args[0]);
}
public double sin(x) { Math.sin(x); return sin(x); }
}
4 ответа
Отрывок из ответа на аналогичный вопрос...
Параметры и локальные переменные размещаются в стеке (со ссылочными типами объект живет в куче, а переменная ссылается на этот объект). Стек обычно располагается в верхнем конце вашего адресного пространства и по мере его использования он направляется к нижней части адресного пространства (т. Е. К нулю).
У вашего процесса также есть куча, которая живет в нижней части вашего процесса. По мере выделения памяти эта куча может увеличиваться в направлении верхнего края вашего адресного пространства. Как видите, у кучи есть вероятность "столкнуться" со стеком (немного похоже на техтонические пластины!!!).
Ошибка переполнения стека означает, что стек (ваш метод) переполнен (выполнялся сам столько раз, что падал). Ошибки переполнения стека обычно являются результатом неправильного рекурсивного вызова.
Как правило, если имя вашего метода не имеет ключевого слова void
в этом, убедитесь, что return
значение не совпадает с именем метода. В противном случае стек переполнится, что приведет к сбою вашей программы. Просто замените эти строки:
Math.sin(x);
return sin(x);
... с этой строкой...
return Math.sin(x);
... и тебе надо идти!
Иногда может быть немного сложно определить, когда произойдет сбой программы:
Q: Эта программа потерпит крах? Если так, то почему?
public void MultiplyByNintyNine(byte num) {
MultiplyByNintyNine(num * 99);
}
A: На самом деле, это может привести к сбою по двум причинам:
Число может стать настолько большим, что JVM не сможет его обработать.
Функция может вызывать себя так много раз, что JVM падает (то есть ошибка переполнения стека).
Последний случай является более разумным; хотя метод на самом деле не return
что-нибудь, метод все еще вызывается.
В некоторых случаях вполне нормально return
название метода. Просто убедитесь, что у вас есть условие завершения, если вы это сделаете! Вот пример, похожий на ваш (который не падает):
import java.io.*;
//class declaration here
public static void main(String[] args) {
System.out.println(guessTheNumber());
}
public String guessTheNumber() {
int guess;
System.out.print("Guess the number:_");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
try {
guess = Integer.parseInt(br.readLine());
} catch (NumberFormatException e) {
System.err.println("You didn't guess a number.");
guessTheNumber();
} catch (IOException e) {
System.err.println("An unexpected error occured. Please try again.");
guessTheNumber();
}
if (guess == 4) {
return "YAY! You get a prize!";
} else {
System.err.println("WAAHH! You get to guess again!");
guessTheNumber();
}
}
Предупреждение. Единственный способ остановить этот код (из самого кода) - ввести 4
,
В приведенном выше случае условие завершения возникает, когда пользователь вводит фактическое число, и это число равно 4.
PS Если у вас плохое настроение, вот настоящая ошибка StackOverFlow!
Я не уверен, почему это дает ошибку stackru, но это не является допустимым Java.
Метод sin не объявляет тип входного параметра. Строковые аргументы должны быть преобразованы в удвоенные, чтобы Math.sin работал. Имя класса нарушает соглашение о кодировании Java (не ошибка). Ошибки должны были быть обнаружены компилятором Java. Компилятор выдавал какие-либо ошибки?
Ваш код близок, но sin
функция действительно должна быть
public double sin(double x) {
return Math.sin(x);
}
Обратите внимание, что мы можем просто вернуть значение Math.sin(x)
, Нет необходимости возвращать `sin(x)~ впоследствии.
Ваш метод sin вызывает сам себя, так что это будет продолжаться бесконечно, пока вы не достигнете предела стека вызовов, где вы получите свое исключение. Почему бы вам просто не вернуть Math.sin()?