tags:

views:

2153

answers:

4

Posting a stack overflow question on stackoverflow.com, how amusing :-)

I'm running some recursive Ruby code and I get the: "Stack level too deep (SystemStackError)"

(I'm quite sure the code works, that I'm not in an infinite recursive death spiral, but that is not the point anyway)

Is there anyway to change the allowed stack depth/size for my Ruby app?

I don't quite get it if this is a restriction in Ruby, since the error says "Stack level", which gives me the impression that Ruby somehow counts 'levels' of stack, or if it simply means that the stack is full.

I have tried running this program under both Vista and Ubuntu with same result. Under Ubuntu i tried changing the stack size with 'ulimit -s' from 8192 to 16000, but that didn't change anything.

Edit: Thanks for the feedback.
I do realize that using a recursive function perhaps isn't the most robust way to go. But that isn't the point either. I simply wonder if there is a way to increase the stack size.. period. And as I mentioned i did try running ulimit -s 16000 before running the ruby script.. with no improvement.. Am I using it wrong?

Edit2: I was in fact having an infinite recursion in an edge case of the code.
The truncated ruby stack trace when you get the "Stack level too deep" error is a bit misleading.
When having a recursive behavior involving several functions, you get the impression that the numbers of recursions is much lower than it actually is. In this example one might thing that it crashes after little bit more than 190 calls, but it is actually around 15000 calls

tst.rb:8:in `p': stack level too deep (SystemStackError)
        from tst.rb:8:in `bar'
        from tst.rb:12:in `bar'
        from tst.rb:19:in `foo'
        from tst.rb:10:in `bar'
        from tst.rb:19:in `foo'
        from tst.rb:10:in `bar'
        from tst.rb:19:in `foo'
        from tst.rb:10:in `bar'
         ... 190 levels...
        from tst.rb:19:in `foo'
        from tst.rb:10:in `bar'
        from tst.rb:19:in `foo'
        from tst.rb:22

-Andreas

+5  A: 

Yukihiro Matsumoto writes here

Ruby uses C stack, so that you need to use ulimit to specify a limit on stack depth.

Alexander Prokofyev
+1  A: 

Ruby uses the C stack so your options include using ulimit or compiling Ruby with some compiler/linker stack size flag. Tail recursion is yet to be implemented and Ruby's current support for recursion isn't so great. As cool and elegant recursion is, you might want to consider coping with the language's limitations and writing your code in a different way.

Firas Assaad
+3  A: 

Think about what is going on with the code. As other posters have mentioned it is possible to hack the C code of the interpreter. However. the result will be that you are using more RAM and have no guarantee that you won't blow the stack again.

The really good solution would be to come up with an iterative algorithm for what you are trying to do. Sometimes memoisation can help and sometimes you find you are not using the stuff you are pushing on the stack in which case you can replace recursive calls with mutable state.

If you are new to this sort of stuff have a look at SICP here for some ideas...

domgblackwell
+2  A: 

If you are sure that you do not have an Infinite recursion situation then your algorythm is pobably not suited for Ruby to execute it in a recirsive manner. Converting an algorythm from recursion to different kind of stack is pretty easy and I suggest you try that. Here is how you can do it.

def recursive(params)
  if some_conditions(params)
     recursive(update_params(params))
  end
end

recursive(starting_params)

will transform into

stack = [starting_params]
while !stack.empty?
  current_params = stack.delete_at(0)
  if some_conditions(current_params)
    stack << update_params(current_params)
  end
end
Honza