なんか特定の条件でサーバが重くなるなぁ、と思ったら無限ループでした。
注意すべきコード
以下のようなループは無限ループとなる可能性があるので注意
(0..max).each do |i|
# 何か処理
end
なぜ?
Range クラスの仕様で終端が省略されている or nil の場合の Range オブジェクトは「終端なしのRangeオブジェクト」となる。
An “endless range” represents a semi-infinite range. Literal notation for an endless range is:
(1..)
# or similarly
(1...)
Which is equivalent to
(1..nil) # or similarly (1...nil)
Range.new(1, nil) # or Range.new(1, nil, true)
よって、前述のコードでは max
が nil
となる場合、無限ループとなる。
じゃあどうしたら?
以下のように #upto()
のループに置き換える
0.upto(max) do |i|
# 何か処理
end
max
に nil
が入る余地を無くすというのも手ですが、そもそも無限ループしない書き方にしたい。
upto
に nil
を渡すと例外が発生するので、少なくとも無限ループすることはあり得ない。