在stackoverflow.com上发布堆栈溢出问题,有多么有趣:-)
我正在运行一些递归的Ruby代码,我得到: "Stack level too deep (SystemStackError)"
(我很确定代码是有效的,我不是在无限的递归死亡螺旋中,但这不是重点)
有没有改变我的Ruby应用程序允许的堆栈深度/大小?
如果这是Ruby中的限制,我不太明白,因为错误说"堆栈级别",这让我觉得Ruby以某种方式计算堆栈的"级别",或者它只是意味着堆栈已满.
我试过在Vista和Ubuntu下运行这个程序,结果相同.在Ubuntu下我尝试用'ulimit -s'将堆栈大小从8192更改为16000,但这并没有改变任何东西.
编辑:感谢您的反馈.
我确实意识到使用递归函数可能不是最强大的方法.但这也不是重点.我只是想知道是否有办法增加堆栈大小..期间.正如我所提到的,我确实尝试在运行ruby脚本之前运行ulimit -s 16000 ..没有任何改进..我使用它错了吗?
Edit2:事实上我在代码的边缘情况下有一个无限递归.
当您收到"Stack level too deep"
错误时,截断的ruby堆栈跟踪有点误导.
当具有涉及多个函数的递归行为时,您会得到递归数量远低于其实际值的印象.在这个示例中,可能会在超过190次调用后崩溃,但实际上大约有15000次调用
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
这个问题及其答案似乎可以追溯到使用C堆栈的Ruby 1.8.x. Ruby 1.9.x及更高版本使用具有自己堆栈的VM.在Ruby 2.0.0及更高版本中,可以通过RUBY_THREAD_VM_STACK_SIZE
环境变量控制VM堆栈的大小.
如果您确定没有无限递归情况,那么您的algorythm可能不适合Ruby以一种重复的方式执行它.将algorythm从递归转换为不同类型的堆栈非常简单,我建议你尝试一下.这是你如何做到的.
def recursive(params) if some_conditions(params) recursive(update_params(params)) end end recursive(starting_params)
将转变为
stack = [starting_params] while !stack.empty? current_params = stack.delete_at(0) if some_conditions(current_params) stack << update_params(current_params) end end
Yukihiro Matsumoto在这里写道
Ruby使用C堆栈,因此您需要使用ulimit来指定堆栈深度的限制.
Ruby使用C堆栈,因此您的选择包括使用ulimit或使用某些编译器/链接器堆栈大小标志编译Ruby.尾递归尚未实现,Ruby目前对递归的支持并不是那么好.作为酷炫优雅的递归,您可能需要考虑应对语言的限制并以不同的方式编写代码.