

以下、問題再現のために無理矢理書いたコードです。  
(実際は、多少入り組んだ rspec のファイルを rubocop でパースした際に遭遇しました)

[code]

    # 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)
    
[/code]

このコードを、DockerHub で配布されている Docker イメージ `ruby:2.5.0-alpine3.7`
で実行すると、比較的浅い段階で例外になります。

[code]

    % 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)
    
[/code]

一方で、Ruby のソース以外は同等である Docker イメージ `ruby:2.4.3-alpine3.7` では比較的深めの段階で例外となります。

[code]

    % 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>'
    
[/code]

加えて、Debian 版の Docker イメージ `ruby:2.5.0-stretch` で実行すると、比較的深めの段階で例外となります。

[code]

    % 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)
    
[/code]

この違いは、Ruby によるものでしょうか？それとも Linux (実行環境)によるものでしょうか？


CC BY-SA 3.0
2017-12-29T12:46:20.370
40605
2017-12-29T12:46:20.370
26830
question
ruby
Alpine Linux 3.7 でコンパイルした Ruby 2.5.0 が比較的浅い再帰で SystemStackError となる理由を教えてください