Alpine Linux 3.7 でコンパイルした Ruby 2.5.0 が比較的浅い再帰で SystemStackError となる理由を教えてください
以下、問題再現のために無理矢理書いたコードです。
(実際は、多少入り組んだ rspec のファイルを rubocop でパースした際に遭遇しました)
# test.rb
n = 100000
res = {}
1.upto(n).to_a.inject(res) do |r, i|
r[i] = {}
end
def f(x)
x.each_value { |v| f(v) }
end
f(res)
このコードを、DockerHub で配布されている Docker イメージ ruby:2.5.0-alpine3.7
で実行すると、比較的浅い段階で例外になります。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.5.0-alpine3.7 ruby -v /mnt/my/test.rb
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux-musl]
Traceback (most recent call last):
149: from /mnt/my/test.rb:11:in `<main>'
148: from /mnt/my/test.rb:8:in `f'
147: from /mnt/my/test.rb:8:in `each_value'
146: from /mnt/my/test.rb:8:in `block in f'
145: from /mnt/my/test.rb:8:in `f'
144: from /mnt/my/test.rb:8:in `each_value'
143: from /mnt/my/test.rb:8:in `block in f'
142: from /mnt/my/test.rb:8:in `f'
... 137 levels...
4: from /mnt/my/test.rb:8:in `f'
3: from /mnt/my/test.rb:8:in `each_value'
2: from /mnt/my/test.rb:8:in `block in f'
1: from /mnt/my/test.rb:8:in `f'
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
一方で、Ruby のソース以外は同等である Docker イメージ ruby:2.4.3-alpine3.7
では比較的深めの段階で例外となります。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.4.3-alpine3.7 ruby -v /mnt/my/test.rb
ruby 2.4.3p205 (2017-12-14 revision 61247) [x86_64-linux-musl]
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:8:in `block in f'
... 10067 levels...
from /mnt/my/test.rb:8:in `block in f'
from /mnt/my/test.rb:8:in `each_value'
from /mnt/my/test.rb:8:in `f'
from /mnt/my/test.rb:11:in `<main>'
加えて、Debian 版の Docker イメージ ruby:2.5.0-stretch
で実行すると、比較的深めの段階で例外となります。
% docker container run -v (pwd):/mnt/my --rm -it ruby:2.5.0-stretch ruby -v /mnt/my/test.rb
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-linux]
Traceback (most recent call last):
9878: from /mnt/my/test.rb:11:in `<main>'
9877: from /mnt/my/test.rb:8:in `f'
9876: from /mnt/my/test.rb:8:in `each_value'
9875: from /mnt/my/test.rb:8:in `block in f'
9874: from /mnt/my/test.rb:8:in `f'
9873: from /mnt/my/test.rb:8:in `each_value'
9872: from /mnt/my/test.rb:8:in `block in f'
9871: from /mnt/my/test.rb:8:in `f'
... 9866 levels...
4: from /mnt/my/test.rb:8:in `f'
3: from /mnt/my/test.rb:8:in `each_value'
2: from /mnt/my/test.rb:8:in `block in f'
1: from /mnt/my/test.rb:8:in `f'
/mnt/my/test.rb:8:in `each_value': stack level too deep (SystemStackError)
この違いは、Ruby によるものでしょうか?それとも Linux (実行環境)によるものでしょうか?