Is it possible to create "SystemStackError: stack level too deep" errors without recursion?
考虑以下 irb 交互:
1 2 3 4 5 6 | 2.1.1 :001 > def do_it 2.1.1 :002?> do_it 2.1.1 :003?> end => :do_it 2.1.1 :004 > do_it SystemStackError: stack level too deep |
在这个例子中,它是检测出栈用尽的确定性还是真的用尽了栈?不使用递归是否可能产生此错误?
In this example, does it detect the certainty of running out of stack or does it actually run out of stack?
它实际上用完了堆栈。实际上,由于计算机科学的核心问题之一的停机问题,在一般情况下"检测到堆栈耗尽的确定性"是不可能的。
Is it possible to produce this error without using recursion?
当然。只需定义很多方法,每个方法调用下一个:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 20000.times do |n| define_method :"foo_#{n}" do puts"Called #{__method__}" send :"foo_#{n+1}" end end foo_0 # -> Called foo_0 # -> Called foo_1 # -> Called foo_2 # -> Called foo_3 # ... # -> Called foo_4931 # -> SystemStackError: stack level too deep |
它确实达到了它的最大堆栈限制...
1 2 3 4 5 | def do_it x=1 puts"Do it #{x}" do_it x+1 end do_it |
以下是对 Ruby 堆栈限制的合理解释:如何增加 ruby?? 应用程序的堆栈大小。递归应用程序获取:堆栈级别太深 (SystemStackError)
Ruby 堆栈细节总结
礼貌@gregspurrier:
- v1.8.x 使用 C 堆栈
- v1.9.x 使用具有自己堆栈的虚拟内存
-
v2.0.0 这个虚拟机限制可以通过
RUBY_THREAD_VM_STACK_SIZE 设置
它实际上耗尽了堆栈上的空间。
每个方法调用都需要堆栈上的一些空间。你可以有这样的代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | def method_1 method_2 end def method_2 method_3 end ... ... def method_123456 method_123457 end method_1 |
不涉及递归,但它仍然会在某些时候耗尽堆栈空间。