简体   繁体   English

Java - StackOverFlow错误

[英]Java - StackOverFlow error

So thanks to @fireshadow52, I've managed to come up with this script that sin s args[0] . 所以多亏了@ fireshadow52,我已经成功地想出了这个sin的脚本args[0] However, it spits out a StackOverFlow error . 但是,它会吐出StackOverFlow error What is this, and how (if possible) would you spot them? 这是什么,以及如何(如果可能的话)你会发现它们?

class SIN {
    public static void main(String[] args) {
        double result = sin(args[0]);
    }
    public double sin(x) { Math.sin(x); return sin(x); }
}

I'm not sure why it is giving a stackoverflow error but this is not valid java. 我不确定为什么它会给出stackoverflow错误,但这不是有效的java。

The sin method doesn't declare a type of the input parameter. sin方法不声明输入参数的类型。 The string args need to be converted to double for Math.sin to work. 字符串args需要转换为double才能使Math.sin工作。 The class name breaks java coding convention (not an error). 类名破坏了java编码约定(不是错误)。 The errors should have been detected by a java compiler. 错误应该由java编译器检测到。 Did the compiler throw any errors? 编译器是否抛出任何错误?

Your sin method is calling itself, so this will continue indefinately until you reach the call stack limit where you get your exception. 你的sin方法正在调用自己,所以这将继续无限期,直到你达到调用堆栈限制,你得到你的异常。 Why don't you just return Math.sin()? 你为什么不直接返回Math.sin()?

An excerpt from an answer to a similar question ... 类似问题的答案中摘录......

Parameters and local variables are allocated on the stack (with reference types the object lives on the heap and a variable references that object). 参数和局部变量在堆栈上分配(对象存在于堆上的引用类型和引用该对象的变量)。 The stack typically lives at the upper end of your address space and as it is used up it heads towards the bottom of the address space (ie towards zero). 堆栈通常位于地址空间的上端,当它用完时,它朝向地址空间的底部(即朝向零)。

Your process also has a heap, which lives at the bottom end of your process. 您的进程还有一个堆,它位于流程的底端。 As you allocate memory this heap can grow towards the upper end of your address space. 在分配内存时,此堆可以向地址空间的上端增长。 As you can see, there is the potential for the heap to "collide" with the stack (a bit like techtonic plates!!!). 正如你所看到的,堆有可能与堆栈“碰撞”(有点像技术板块!!!)。

A Stack Overflow error means that the stack (your method) overflowed (executed itself so many times that it crashed). 堆栈溢出错误意味着堆栈(您的方法)溢出(自身执行了很多次以至于崩溃)。 Stack Overflow errors usually result from a bad recursive call. 堆栈溢出错误通常是由错误的递归调用引起的。

In general, if your method name doesn't have the keyword void in it, make sure the return value isn't the same as the method name. 通常,如果您的方法名称中没有关键字void ,请确保return值与方法名称不同。 Otherwise, the stack will overflow, crashing your program. 否则,堆栈将溢出,导致程序崩溃。 Just replace these lines: 只需替换这些行:

Math.sin(x);
return sin(x);

...with this line... ......用这条线......

return Math.sin(x);

...and you should be good to go! ......你应该好好去!

Sometimes in can be a bit tricky to find out when a program will crash: 有时在查找程序崩溃时可能会有点棘手:

Q: Will this program crash? 问:这个程序会崩溃吗? If so, why? 如果是这样,为什么?

public void MultiplyByNintyNine(byte num) {
    MultiplyByNintyNine(num * 99);
}

A: Actually, this could crash for two reasons: 答:实际上,这可能会因以下两个原因而崩溃:

  1. The number could get so large that the JVM can't handle it. 数量可能会变得很大,以至于JVM无法处理它。

  2. The function could call itself so many times that the JVM crashes (ie a Stack Overflow error). 该函数可以调用自身很多次以至于JVM崩溃(即堆栈溢出错误)。

The latter case is the more reasonable; 后一种情况更合理; even though the method doesn't actually return anything, the method is still called. 即使该方法实际上没有return任何内容,仍然会调用该方法。

In some cases, it is perfectly OK to return the method name. 在某些情况下, return方法名称是完全可以的。 Just make sure you have a terminating condition if you do, though! 但是,如果你这样做,请确保你有终止条件! Here is an example similar to yours (that doesn't crash): 这是一个类似于你的例子(不会崩溃):

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();
    }
}

Warning: The only way to stop this code (from the code itself) is to enter 4 . 警告:停止此代码(从代码本身)的唯一方法是输入4

In the above case, the terminating condition occurs when a user enters an actual number and that number is 4. 在上述情况下,当用户输入实际号码并且该号码是4时,发生终止条件。


PS If you're feeling down, here is a REAL StackOverFlow error! PS如果你感到沮丧, 这是一个真正的 StackOverFlow错误!

Your code is close, but the sin function should really be 你的代码很接近,但sin函数应该是真的

public double sin(double x) {
    return Math.sin(x);
}

Notice that we can simply return the value of Math.sin(x) . 请注意,我们只需返回Math.sin(x)的值即可。 No need to return `sin(x)~ afterwards. 之后不需要返回`sin(x)〜。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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