Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why am I getting a stackoverflow?

Tags:

clojure

I've been playing around with Clojure and I managed to blow the stack. In this piece of code, I use recursion only with recur. I am doing a lot of concatenation (note calls to concat in the trace below). I tried to doall on all concatenated lists, since these are lazy and I wanted them evaluated as I went along. I still get a stack overflow. Here's the trace. I am thinking this might be a common issue and someone with more experience hacking clojure can point me in the right direction.

Here's the piece of code that was causing the problem.

(defn move-split [[xs ys]] (doall (concat (list (concat xs (list (first ys))))  (list (next ys)))))

I put the doall in there because of the stackoverflow, but that still did not solve the problem.

(defn move-split [[xs ys]] (doall (concat (list (doall (concat xs (list (first ys))))  ) (doall (list (next ys)))   )))

Notice the extra doalls? Here, everwhere I call concat I filter the result through a doall. Stackoverflow gone.

doall does not seem to be recursive. That is nested lists that are also results of concat are not evaluated. What do you think?

Exception in thread "main" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at jline.ConsoleRunner.main(Unknown Source)
Caused by: java.lang.StackOverflowError (bubble_sort2.clj:0)
    at clojure.lang.Compiler.eval(Compiler.java:5440)
    at clojure.lang.Compiler.load(Compiler.java:5857)
    at clojure.lang.Compiler.loadFile(Compiler.java:5820)
    at clojure.main$load_script.invoke(main.clj:221)
    at clojure.main$script_opt.invoke(main.clj:273)
    at clojure.main$main.doInvoke(main.clj:354)
    at clojure.lang.RestFn.invoke(RestFn.java:409)
    at clojure.lang.Var.invoke(Var.java:365)
    at clojure.lang.AFn.applyToHelper(AFn.java:163)
    at clojure.lang.Var.applyTo(Var.java:482)
    at clojure.main.main(main.java:37)
    ... 5 more
Caused by: java.lang.StackOverflowError
    at clojure.core$seq.invoke(core.clj:122)
    at clojure.core$concat$fn__3450.invoke(core.clj:599)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:450)
    at clojure.core$seq.invoke(core.clj:122)
    at clojure.core$concat$fn__3450.invoke(core.clj:599)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:450)
    at clojure.core$seq.invoke(core.clj:122)
    at clojure.core$concat$fn__3450.invoke(core.clj:599)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:450)
    at clojure.core$seq.invoke(core.clj:122)
    at clojure.core$concat$fn__3450.invoke(core.clj:599)
    at clojure.lang.LazySeq.sval(LazySeq.java:42)
    at clojure.lang.LazySeq.seq(LazySeq.java:56)
    at clojure.lang.RT.seq(RT.java:450)
    at clojure.core$seq.invoke(core.clj:122)
    at clojure.core$concat$fn__3450.invoke(core.clj:599)
like image 964
yalis Avatar asked Mar 14 '11 02:03

yalis


People also ask

Why am I getting a stack overflow error?

A StackOverflowError is a runtime error in Java. It is thrown when the amount of call stack memory allocated by the JVM is exceeded. A common case of a StackOverflowError being thrown, is when the call stack exceeds due to excessive deep or infinite recursion.

How do I stop stack overflow?

One method to prevent stack overflow is to track the stack pointer with test and measurement methods. Use timer interrupts that periodically check the location of the stack pointer, record the largest value, and watch that it does not grow beyond that value.

How is stack overflow detected?

A method of detecting stack overflows is to create a canary space at the end of each task. This space is filled with some known data. If this data is ever modified, then the application has written past the end of the stack.

Is stackoverflow considered cheating?

Generally speaking, taking code from Stack Overflow is not cheating. However, there are some exceptions. If you are set an assignment at school or college and told not to seek outside help, don't cheat. Using platforms like SO, Google, and other community forums, is cheating.


1 Answers

You're piling up a bunch of lazy operations all in a row, building up an expression like

(concat (concat (concat ... [3]) [2]) [1])

or similar. In order to determine even the first element in the resulting list, the compiler must drill deeply into this stack of functions you've given it. Try to structure your code so that this doesn't happen, or throw in a (doall) every so often to force eager/strict computations. I can't really go into more detail with just a stack trace, though - code would help.

like image 150
amalloy Avatar answered Sep 18 '22 22:09

amalloy