Gyakorlati alapok II.
Rekurzió
Végtelen rekurzió
Bevezetésképpen nézzük meg az előző fejezet faktoriális-számításának már ismertetett, rekurzív kódját:
public class Main {
static int faktorialis (int bemenetiAdat){
if (bemenetiAdat <= 1){
return 1;
}
return bemenetiAdat *
faktorialis(bemenetiAdat-1);
}
public static void main(String[] args) {
System.out.println(faktorialis(5));
}
}
Végeredmény:
120
Mivel a rekurzió önmagát meghívó függvénymegoldás és ennek implementálása viszonylag könnyű, ezért könnyen implementálhatunk végtelen ciklust. A fenti Java-kódban elég csak a megfelelő paraméter-beállításban hibáznunk...
bemenetiAdat * faktorialis(bemenetiAdat-1)
helyett
bemenetiAdat * faktorialis(bemenetiAdat)
...hogy végtelen függvényhívásba kerülve elfogyjon a hívási verem (call stack) számára fenntartott memóriaterület és veremtúlcsordulási hibával (stack overflow error) megszakadjon a program, Eclipse esetén pedig regény hosszúságú hibaüzenetet kapjunk:
public class Main {
static int faktorialis (int bemenetiAdat){
if (bemenetiAdat <= 1){
return 1;
}
return bemenetiAdat *
faktorialis(bemenetiAdat);
}
public static void main(String[] args) {
System.out.println(faktorialis(5));
}
}
Végeredmény:
Exception in
thread "main" java.lang.StackOverflowError
at Main.faktorialis(Main.java:93)
at Main.faktorialis(Main.java:93)
at Main.faktorialis(Main.java:93)
at Main.faktorialis(Main.java:93)
at Main.faktorialis(Main.java:93)
...
Amint azt a bevezető fejezetben tisztáztuk, nagyon könnyen írhatunk végtelen rekurziót olyan módon, hogy nem teszünk a kódba belső szabályozást. Ekkor a függvény korlátlanul fogja hívogatni magát:
public class Main {
static void vegtelenRekurzio(){
System.out.println("Végtelen rekurzió");
vegtelenRekurzio();
}
public static void main(String[] args) {
vegtelenRekurzio();
}
}
Végeredmény:
Végtelen rekurzió
Végtelen rekurzió
Végtelen rekurzió
Végtelen rekurzió
Végtelen rekurzió
...
Exception in thread "main" java.lang.StackOverflowError
at sun.nio.cs.SingleByte.withResult(Unknown Source)
at sun.nio.cs.SingleByte.access$000(Unknown Source)
at sun.nio.cs.SingleByte$Encoder.encodeArrayLoop(Unknown Source)
at sun.nio.cs.SingleByte$Encoder.encodeLoop(Unknown Source)
at java.nio.charset.CharsetEncoder.encode(Unknown Source)
at sun.nio.cs.StreamEncoder.implWrite(Unknown Source)
at sun.nio.cs.StreamEncoder.write(Unknown Source)
at java.io.OutputStreamWriter.write(Unknown Source)
at java.io.BufferedWriter.flushBuffer(Unknown Source)
at java.io.PrintStream.write(Unknown Source)
at java.io.PrintStream.print(Unknown Source)
at java.io.PrintStream.println(Unknown Source)
at Main.vegtelenRekurzio(Main.java:5)
at Main.vegtelenRekurzio(Main.java:6)
...
A kiírás egy ideig fut, de a veremmemória megtelése miatt hibaüzenettel
garantáltan le fog állni.