[ruby-list:50636] Ruby 2.4.3 で発生しない SystemStackError が Ruby 2.5.0 で発生する理由が分かりません

From: 鈴木将高 <koshigoeb@...>
Date: 2017-12-30 02:03:03 UTC
List: ruby-list #50636
鈴木と申します。

Alpine Linux 3.7 にて、Ruby 2.4.3 では発生しなかった SystemStackError が
Ruby 2.5.0 で発生する様になりました。これは、実行(コンパイル)環境に依存
する問題だと考えたら良いでしょうか?(スレッドスタックサイズ?)

単純な再帰(def f; f; end; f)では深さに違いがありませんが、検証のために無
理矢理書いた以下の様なコードだと例外発生時の深さが大きく違います。
この深さが大きく異なる理由が分かりません。

    # 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)

例えば、Docker Hub の Docker イメージ ruby:2.5.0-alpine3.7 を使うと
137 levels で止まります。

    % 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)

一方で、Docker Hub の Docker イメージ ruby:2.4.3-alpine3.7 を使うと
10067 levels で止まります。
(ruby:2.5.0-alpine3.7 と ruby:2.4.3-alpine3.7 の違いは Ruby のバージョン指定のみ)

    % 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>'

また、Docker Hub の Docker イメージ ruby:2.5.0-stretch を使うと
9866 levels で止まりました。

    % 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)

In This Thread

Prev Next