如何防止收集对Ruby对象的本地引用

时间:2012-07-17 08:06:33

标签: ruby ruby-c-extension

我遇到这种情况,我必须在ruby线程内部而不是ruby线程中用C ++代码构造一些更大的ruby数据结构。

在堆栈上创建的ruby对象是否必须经过特殊处理才能被ruby GC收集?如果对象是在红宝石或非红宝石线上创建的,它会有什么不同吗?

示例:

VALUE h = rb_hash_new(); 
VALUE k = rb_str_new2( "foo" );
VALUE v = rb_str_new2( "foo" );
rb_hash_aset( h, k, v );

我希望每个函数调用都可以分配内存,从而调用垃圾收集器。我是否必须特别注意保护h,k和v不被收集,直到可通过任何全局变量到达?也许是这样的:

VALUE h = Qnil;
VALUE k = Qnil;
VALUE v = Qnil;
rb_gc_register_address( &h ); 
rb_gc_register_address( &k ); 
rb_gc_register_address( &v ); 

VALUE k = rb_str_new2( "foo" );
VALUE v = rb_str_new2( "foo" );

rb_hash_aset( h, k, v );

rb_gc_unregister_address( &k ); 
rb_gc_unregister_address( &v ); 

第二个版本要复杂得多,所以我想避免使用它,如果有任何担保,GC会扫描所有线程以寻找可能的引用。

编辑:我刚刚意识到,我可能不应该使用rb_gc等函数来自一个不能保存gvl的非ruby线程。因此有了保证,GC将标记来自ruby堆栈的引用就足够了。

TIA 托

1 个答案:

答案 0 :(得分:1)

根据我的理解,GC扫描所有堆栈中的任何看起来像是指向ruby对象的指针,并以这种方式将其发现的任何内容视为正在使用的对象。

据我所知,在非ruby线程上创建ruby对象并不支持