From: Hisham Muhammad Date: 2006-06-12T05:34:50+09:00 Subject: Validity of local VALUEs Hi, I've been wondering about the lifetime of Ruby objects declared from C functions. Assume I create a new object through the C API (say, with rb_class_new_instance or rb_ary_new) without exporting it to Ruby or marking it as a global with rb_global_variable. I would expect that this object might be garbage-collected during the execution of my C function, making the VALUE invalid. I tried to write a small test case that caused this: #include static VALUE a_class; static ID a_method_ID; static VALUE a_method(VALUE self) { VALUE an_object; VALUE will_i_get_this; int i; /* Create a Ruby object, but don't bind it anywhere */ an_object = rb_class_new_instance(0, NULL, a_class); rb_iv_set(an_object, "@an_attribute", rb_str_new2("42")); /* Cause some garbage collection cycles */ for (i = 0; i < 100000; i++) { VALUE some_garbage = rb_ary_new(); rb_ary_push(some_garbage, rb_str_new2("666")); /* Looking at the object counts, gc is really happening */ rb_eval_string("print 'objects: ', ObjectSpace.each_object {}, '\n'"); } /* I'd expect an_object to have been collected by now */ will_i_get_this = rb_iv_get(an_object, "@an_attribute"); fprintf(stderr, "The answer is %s.\n", RSTRING(will_i_get_this)->ptr); } int main(int argc, char** argv) { VALUE an_instance; ruby_init(); a_class = rb_define_class("RubyGcTest", rb_cObject); rb_define_method(a_class, "a_method", a_method, 0); an_instance = rb_class_new_instance(0, NULL, a_class); a_method_ID = rb_intern("a_method"); rb_funcall2(an_instance, a_method_ID, 0, NULL); ruby_finalize(); return 0; } I would expect this to crash, but it doesn't. Looking at the object counts returned by ObjectSpace.each_object, I can see that several gc cycles are taking place. However, an_object is still valid by the end of the function. Is this working "by chance"? From the observation that I don't have 100000 array objects in the ObjectSpace after calling rb_ary_new 100000 times, I gather that VALUEs do not remain valid until the end of the function without being bound somewhere. However, my calls to an_object are still returning the correct value. Thanks in advance, -- Hisham