According to the Java VM specs, ยง3.5.2, the vm should throw StackOverflowError or OutOfMemoryError when the stack is full or there's no more memory for the dynamic stack. GCJ doesn't do this. Consider the test program below. Here's the result of running it in some different x86 environments: gcj (gcj -o recurse --main=recurse recurse.java) Segmentation fault after >40000, <50000 recursions Blackdown JDK 1.2.2 Segmentation fault after >40000, <50000 recursions gcj -O2 Never exists - infinite recursion due to tail recursion optimization IBM JDK 1.1.8 Never exists - infinite recursion due to tail recursion optimization IBM JDK 1.3.0 Never exists - infinite recursion due to tail recursion optimization IBM JDK 1.1.8 -nojit StackOverflowException with very long stack trace (>9000 lines) gij Segmentation fault after >2000, <3000 recursions Release: unknown Environment: gcc/gcj 2.96 20000904 How-To-Repeat: import java.util.Vector; public class recurse { public static void main(String[] args) { recurse(0); } public static void recurse(int level) { if (level < 10000) { if (level % 1000 == 0) System.out.println(level); } else if (level < 100000) { if (level % 10000 == 0) System.out.println(level); } else if (level % 100000 == 0) { System.out.println(level); } recurse(level+1); } }
still happens in the mainline (20030524). With stacksize 8192 kbytes tin:~/src/gnu/gcctest>./recurse 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 20000 30000 40000 50000 60000 70000 80000 90000 100000 200000 Segmentation fault (core dumped) tin:~/src/gnu/gcctest>gij recurse 0 1000 2000 3000 4000 5000 6000 7000 8000 9000 10000 Segmentation fault (core dumped)
One way of fixing this having a signal catcher for SIGSEGV but from the glibc's signal man page: According to POSIX, the behaviour of a process is undefined after it ignores a SIGFPE, SIGILL, or SIGSEGV signal that was not generated by the kill(2) or the raise(3) functions. So I do not know if it is okay to do it at all?
*** Bug 13605 has been marked as a duplicate of this bug. ***
A library issue and not a front-end one.
> One way of fixing this having a signal catcher for SIGSEGV but from the glibc's signal > man page: > According to POSIX, the behaviour of a process is undefined after it ignores a SIGFPE, > SIGILL, or SIGSEGV signal that was not generated by the kill(2) or the raise(3) functions. This is not very relevant, because in practice, using the proper cautions, catching SIGSEGV coming from a stack overflow works fine. GNU libsigsegv provides the functionality, and GNU clisp and GNU smalltalk use it. It works on Linux, OSF/1, FreeBSD, OpenBSD, NetBSD/Alpha, MacOS X, Solaris, HP-UX/HPPA, IRIX, AIX 4, BeOS, Cygwin, Windows. The only tricky point in using it would be the necessity to extend the stack by a few pages in order to be able to throw the StackOverflowException. Or to throw this exception from within the signal stack. Either of these would be challenging.
Note the word "undefined", on most platforms it will work just fine but it does not have to work on some platforms or even on ones where it looks like it does.
Note at -O1 on the tree-ssa it never exits because of tail recursion optimization also.
See http://gcc.gnu.org/ml/java-patches/2004-q4/msg00230.html.
See also http://gcc.gnu.org/ml/java-patches/2004-q4/msg00241.html
And http://gcc.gnu.org/ml/java-patches/2004-q4/msg00270.html. Hans' threading seems to be broken.
*** Bug 24980 has been marked as a duplicate of this bug. ***
*** Bug 27268 has been marked as a duplicate of this bug. ***
A better testcase comes from PR 27268 which seg faults at all optimizations level currently (though this case can also be optimized out to be an infinite loop really): public class test { public test() { test t = new test(); } public static void main(String argv[]) { new test(); } }
Closing as won't fix as libgcj (and the java front-end) has been removed from the trunk.