关于 ruby??:是否可以在不递归的情况下创建”SystemStackError: stack level too deep”错误?

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

不涉及递归,但它仍然会在某些时候耗尽堆栈空间。