From: ds14050@... Date: 2022-02-09T15:24:48+09:00 Subject: [ruby-dev:51159] Hash#shift を繰り返していると ruby が無応答になる。 はじめまして ds14050 といいます。最近スクリプトではなくインタープリタが 原因で ruby の応答がなくなるケースに遭遇したと思いました。確認をお願いで きますか。 <<<以下再現スクリプト # ウチではだいたい 20 から 30 回で "empty?: true" を最後にして止まる。 # ウチの Ruby-2.5: ruby 2.5.5p157 (2019-03-15 revision 67260) [x64-mingw32] # ウチの Ruby-2.7: ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x64-mingw32] # ウチの Ruby-3.1: ruby 3.1.0p0 (2021-12-25 revision fb4df44d16) [x64-mingw-ucrt] H = {} 100.times{|n| while H.size < n k = Random.rand 0..1<<30 H[k] = 1 # たぶんここで止まる。 end warn "size: #{H.size} before shifting." 0 while H.shift warn "empty?: #{H.empty?}" } warn :exit >>> Hash に要素を詰めて空にしてを 100 回繰り返すスクリプトです。3.1 を含む3 つのバージョンでほぼ確実に止まる(ruby.exe がビジー状態で終了しない)こと を確認しています。2.5 より古い Ruby-1.9 では止まらずに最後まで実行が完了 しました。 Hash を空にする方法として 0 while H.shift の代わりに H.shift until H.empty? を選ぶと最後まで実行が完了するようになったことから呼び出すメ ソッドを揃えて比較したところ、Hash が空になったあとの余分な Hash#shift が何か悪さをしているように思えます。 また、デバッグプリントを増やして確認したところ実際に停止しているのは Hash#shift の行ではなく H[k] = 1 の行であるようでした。 よろしくお願いします。