From: Shugo Maeda Date: 2008-09-02T00:41:51+09:00 Subject: [ruby-dev:36086] Re: x86_64環境でMarshal.dumpの不具合 前田です。 2008/09/01 21:56 Kouichi Ushijima : > 再現コードを以下に示します。本来等しいはずのobjとobj1が等しくないと判定 > されてしまいます。 > > --------- > obj = Array.new(10000) do > Time.now.to_i + (rand * 10).to_i > end > > obj1 = Marshal.load(Marshal.dump(obj)) > p obj1 == obj > # ==> false! > --------- Solaris/x86_64でも再現しました。 以下のコードでも再現するようです。 obj = [1220278665, 1220278662, 1220278661, 1220278661, 1220278656] GC.stress = true s = Marshal.dump(obj) obj1 = Marshal.load(s) p obj1 == obj どうやらmarshal.cのw_object()の以下のif文の条件が真になっているようなのですが、 if (st_lookup(arg->data, obj, &num)) { w_byte(TYPE_LINK, arg); w_long((long)num, arg); return; } dump中にGCが発生すると、一時的に生成したBignumオブジェクトのアドレスが たまたま同じになってしまうため、arg->dataの検索時に誤って以前のオブジェクト にヒットしてリンクとして処理されてしまうようです。 他にもdump中に一時的にオブジェクトを生成している部分がもしあれば、同じよう な問題が発生しそうですね。 対応としてはarg->dataをHashにするとかでしょうか。 -- Shugo Maeda