[ruby-dev:46147] string.c の str_new4 の assert に引っかかってしまいます

From: Sasaki Shingo <ssksng+ml@...>
Date: 2012-09-20 00:20:20 UTC
List: ruby-dev #46147
sasashinと申します。初投稿です。よろしくお願いします。

数十時間回しっぱなしにするスクリプトを 1.9.2-p290 で動かしているのですが、
まれに以下のエラーが出て異常終了してしまうことがあります。
回しなおすとエラーが出なくなるので、再現条件は掴めていません。

---------------
ruby: string.c:663: str_new4: Assertion `(!!((!(((VALUE)((shared)) &
RUBY_IMMEDIATE_MASK) || !(((VALUE)((shared)) & ~((VALUE)RUBY_Qnil)) !=
0)) && (int)(((struct RBasic*)((shared)))->flags & RUBY_T_MASK) !=
RUBY_T_NODE)?(((struct
RBasic*)((shared)))->flags&((((VALUE)1)<<11))):0))' failed.
---------------

string.c の当該箇所を見てみると、str_new4 の中の assert に
引っかかっていることがわかりました。

---------------
static VALUE
str_new4(VALUE klass, VALUE str)
{
    VALUE str2;

    str2 = str_alloc(klass);
    STR_SET_NOEMBED(str2);
    RSTRING(str2)->as.heap.len = RSTRING_LEN(str);
    RSTRING(str2)->as.heap.ptr = RSTRING_PTR(str);
    if (STR_SHARED_P(str)) {
        VALUE shared = RSTRING(str)->as.heap.aux.shared;
        assert(OBJ_FROZEN(shared));                            <=== ここが663行目
        FL_SET(str2, ELTS_SHARED);
        RSTRING(str2)->as.heap.aux.shared = shared;
    }
    else {
        FL_SET(str, ELTS_SHARED);
        RSTRING(str)->as.heap.aux.shared = str2;
    }
    rb_enc_cr_str_exact_copy(str2, str);
    OBJ_INFECT(str2, str);
    return str2;
}
---------------

この assert は、以下のコミットで string.c に追加されていました。
ただし、このコミットで str_new4 が変更されたのは assert の追加だけで、
処理そのものは変更されていないようです。
また、1.9.3-p194 でも str_new4 は上記のコードのままです。

---------------
commit 7915aed8752566f355ab4b19216da96836fd9589
Author: nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>
Date:   Thu Jun 11 17:41:27 2009 +0000

    * string.c (str_replace_shared): shared target must be frozen.
      [ruby-core:23727]
---------------

これまで、このようなエラーに行き当った方はいらっしゃいますか?
また、回避方法(str_new4を通らないスクリプトの書き方…そんなのあるんかいな…)を
ご存知の方がいらっしゃいましたらご教授いただけませんでしょうか。

In This Thread

Prev Next