From: Nobuyoshi Nakada Date: 2008-07-07T10:15:44+09:00 Subject: Re: mysterious memory corruption, very confused Hi, At Mon, 30 Jun 2008 15:47:19 +0900, Seebs wrote in [ruby-talk:306636]: > It is. There's a loop of > VALUE x; > char **foo = malloc(buncha char *); > > for (big list of things) { > x = rb_obj_as_string(y); > foo[i] = GetStringValue(x); > } It's your bug. > The idiom of using rb_obj_as_string, and then using the value, is common in > the Ruby source. It works. ... It works *as long as you don't allocate > anything more before you're done with it*. What ends up happening is that, > if enough of the objects in question need a new string allocated by > rb_obj_as_string, sooner or later you end up invoking the garbage collector. > Now, since there's only one x, the garbage collector assumes the current > rb_obj_as_string() return is in use, *and the others aren't*. So it might, > if it wants the space, free one... And then the memory gets reused. Because you drop the references to the created objects. You have to keep the objects but not only the pointers. > I submitted a more detailed bug report to the ruby-pg project, and I've > adopted a workaround (possibly very inefficient) involving an array of VALUE > objects and rb_gc_{un}register_address. It's ugly but it eliminates the bug. VALUE x, array; char **foo = malloc(buncha char *); for (big list of things) { x = rb_obj_as_string(y); rb_ary_push(array, x); foo[i] = GetStringValue(x); } By keeping the values in an automatic variable `array', they are marked and won't be freed. -- Nobu Nakada