什么是 StackOverflowError
, 它是由什么引起的,我该如何处理它们?
什么是 StackOverflowError
, 它是由什么引起的,我该如何处理它们?
堆栈有一个取决于操作系统的空间限制。通常大小为8 MB(在Ubuntu(Linux)中,您可以使用$ ulimit -u
检查该限制,并且可以类似地在其他操作系统中进行检查)。任何程序在运行时都会使用堆栈,但要完全知道何时使用它,您需要检查汇编语言。例如,在x86_64中,堆栈用于:
如果您不了解x86_64(正常情况),则只需要知道您正在使用的特定高级编程语言何时编译这些操作即可。例如,在C中:
因此,在 C 中,只有局部变量和函数调用使用堆栈。造成堆栈溢出的两种(独特的?)方式是:
int array[10000][10000];
)为避免 StackOverflowError
,您可以:
检查局部变量是否过大(1 MB 的数量级)→ 使用堆(malloc/calloc 调用)或全局变量。
检查无限递归 → 您知道该怎么做... 纠正它!
检查普通的过深递归 → 最简单的方法是将实现更改为迭代式。
ulimit -s 32768
(32 MB)。 (这从未是我任何堆栈溢出错误的解决方案,但我也没有太多经验。)alloc()
的用法及类似情况),因为如果您正在使用它们,则应该已经清楚自己在做什么。public class Example3 {
public static void main(String[] args) {
main(new String[1]);
}
}
一个简单的Java示例,由于错误的递归调用导致java.lang.StackOverflowError:
class Human {
Human(){
new Animal();
}
}
class Animal extends Human {
Animal(){
super();
}
}
public class Test01 {
public static void main(String[] args) {
new Animal();
}
}
这是一个例子
public static void main(String[] args) {
System.out.println(add5(1));
}
public static int add5(int a) {
return add5(a) + 5;
}
StackOverflowError 基本上是指当您尝试执行某些操作时,很可能会调用自身并永无休止地继续下去(或者直到出现 StackOverflowError)。
add5(a)
会调用自身,然后再次调用自身,依此类推。
这是一个典型的 java.lang.StackOverflowError
案例... 方法在 doubleValue()
、floatValue()
等中无限递归调用自身,没有退出。
public class Rational extends Number implements Comparable<Rational> {
private int num;
private int denom;
public Rational(int num, int denom) {
this.num = num;
this.denom = denom;
}
public int compareTo(Rational r) {
if ((num / denom) - (r.num / r.denom) > 0) {
return +1;
} else if ((num / denom) - (r.num / r.denom) < 0) {
return -1;
}
return 0;
}
public Rational add(Rational r) {
return new Rational(num + r.num, denom + r.denom);
}
public Rational sub(Rational r) {
return new Rational(num - r.num, denom - r.denom);
}
public Rational mul(Rational r) {
return new Rational(num * r.num, denom * r.denom);
}
public Rational div(Rational r) {
return new Rational(num * r.denom, denom * r.num);
}
public int gcd(Rational r) {
int i = 1;
while (i != 0) {
i = denom % r.denom;
denom = r.denom;
r.denom = i;
}
return denom;
}
public String toString() {
String a = num + "/" + denom;
return a;
}
public double doubleValue() {
return (double) doubleValue();
}
public float floatValue() {
return (float) floatValue();
}
public int intValue() {
return (int) intValue();
}
public long longValue() {
return (long) longValue();
}
}
public class Main {
public static void main(String[] args) {
Rational a = new Rational(2, 4);
Rational b = new Rational(2, 6);
System.out.println(a + " + " + b + " = " + a.add(b));
System.out.println(a + " - " + b + " = " + a.sub(b));
System.out.println(a + " * " + b + " = " + a.mul(b));
System.out.println(a + " / " + b + " = " + a.div(b));
Rational[] arr = {new Rational(7, 1), new Rational(6, 1),
new Rational(5, 1), new Rational(4, 1),
new Rational(3, 1), new Rational(2, 1),
new Rational(1, 1), new Rational(1, 2),
new Rational(1, 3), new Rational(1, 4),
new Rational(1, 5), new Rational(1, 6),
new Rational(1, 7), new Rational(1, 8),
new Rational(1, 9), new Rational(0, 1)};
selectSort(arr);
for (int i = 0; i < arr.length - 1; ++i) {
if (arr[i].compareTo(arr[i + 1]) > 0) {
System.exit(1);
}
}
Number n = new Rational(3, 2);
System.out.println(n.doubleValue());
System.out.println(n.floatValue());
System.out.println(n.intValue());
System.out.println(n.longValue());
}
public static <T extends Comparable<? super T>> void selectSort(T[] array) {
T temp;
int mini;
for (int i = 0; i < array.length - 1; ++i) {
mini = i;
for (int j = i + 1; j < array.length; ++j) {
if (array[j].compareTo(array[mini]) < 0) {
mini = j;
}
}
if (i != mini) {
temp = array[i];
array[i] = array[mini];
array[mini] = temp;
}
}
}
}
2/4 + 2/6 = 4/10
Exception in thread "main" java.lang.StackOverflowError
2/4 - 2/6 = 0/-2
at com.xetrasu.Rational.doubleValue(Rational.java:64)
2/4 * 2/6 = 4/24
at com.xetrasu.Rational.doubleValue(Rational.java:64)
2/4 / 2/6 = 12/8
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
at com.xetrasu.Rational.doubleValue(Rational.java:64)
main
方法)中添加行new Object() {{getClass().newInstance();}};
。 从实例上下文中不起作用(仅抛出InstantiationException
)。 - John McClane