From: Yusuke ENDOH Date: 2008-10-29T21:34:27+09:00 Subject: [ruby-dev:36983] [Bug:1.9] replacing array during sort may make assertion fail 遠藤です。 以下のようにすると assert が失敗します。 $ ./ruby -e 'a = [4,3,2,1]; a.sort! {|x,y| a.replace([]); x <=> y }' ruby: array.c:1755: rb_ary_sort_bang: Assertion `(((void) ((!((!(((VALUE)(tmp) & RUBY_IMMEDIATE_MASK) || !(((VALUE)(tmp) & ~((VALUE)RUBY_Qnil)) != 0)) && (((struct RBasic*)(tmp))->flags & RUBY_T_MASK) != RUBY_T_NODE)?(((struct RBasic*)(tmp))->flags&((((VALUE)1)<<(12+2)))):0) || !((!(((VALUE)(tmp) & RUBY_IMMEDIATE_MASK) || !(((VALUE)(tmp) & ~((VALUE)RUBY_Qnil)) != 0)) && (((struct RBasic*)(tmp))->flags & RUBY_T_MASK) != RUBY_T_NODE)?(((struct RBasic*)(tmp))->flags&((((VALUE)1)<<(12+1)))):0)) ? 0 : (__assert_fail ("!((!(((VALUE)(tmp) & RUBY_IMMEDIATE_MASK) || !(((VALUE)(tmp) & ~((VALUE)RUBY_Qnil)) != 0)) && (((struct RBasic*)(tmp))->flags & RUBY_T_MASK) != RUBY_T_NODE)?(((struct RBasic*)(tmp))->flags&((((VALUE)1)<<(12+2)))):0) || !((!(((VALUE)(tmp) & RUBY_IMMEDIATE_MASK) || !(((VALUE)(tmp) & ~((VALUE)RUBY_Qnil)) != 0)) && (((struct RBasic*)(tmp))->flags & RUBY_T_MASK) != RUBY_T_NODE)?(((struct RBasic*)(tmp))->flags&((((VALUE)1)<<(12+1)))):0)", "array.c", 1755, __PRETTY_FUNCTION__), 0))), ((!(((VALUE)(tmp) & RUBY_IMMEDIATE_MASK) || !(((VALUE)(tmp) & ~((VALUE)RUBY_Qnil)) != 0)) && (((struct RBasic*)(tmp))->flags & RUBY_T_MASK) != RUBY_T_NODE)?(((struct RBasic*)(tmp))->flags&((((VALUE)1)<<(12+1)))):0))' failed. アボートしました 以下の修正でいいでしょうか。 Index: array.c =================================================================== --- array.c (revision 20023) +++ array.c (working copy) @@ -1751,14 +1751,14 @@ ruby_qsort(RARRAY_PTR(tmp), RARRAY_LEN(tmp), sizeof(VALUE), rb_block_given_p()?sort_1:sort_2, &data); - if (ARY_EMBED_P(ary) || ARY_EMBED_P(tmp)) { + if (ARY_EMBED_P(tmp)) { assert(ARY_EMBED_P(tmp)); MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp)); ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp)); } else { - assert(!ARY_EMBED_P(ary)); assert(!ARY_EMBED_P(tmp)); + if (ARY_EMBED_P(ary)) FL_UNSET_EMBED(ary); if (RARRAY_PTR(ary) != RARRAY_PTR(tmp)) { assert(!ARY_SHARED_P(tmp)); if (ARY_SHARED_P(ary)) { -- Yusuke ENDOH