Rb_protect / rb_eval_string and the GC in Ruby 1.8.7


#1

Hi!

At the moment I’m trying to extend an application with embedded Ruby and
therefore try to understand the garbage collection mechanisms.

For a simple class that just prints when it’s ctor and dtor are called,
I’ve created the Ruby wrapping code with Swig. Now I do this:

in Ruby:

def get_new_bar
puts “DEBUG: get_new_bar”
return Swig::Bar.new
end

In C++:


rb_eval_string(“get_new_bar”);
rb_eval_string(“puts 'DEBUG: '; GC.start; puts 'DEBUG: '”);

ruby_finalize();

What happens is exactly, what one would expect:

DEBUG: Bar::Bar()
DEBUG: get_new_bar
DEBUG:
DEBUG: Bar::~Bar();
DEBUG:

Now I change this to:


rb_protect(get_new_bar_eval_wrapper, 0, &error);
rb_eval_string(“puts 'DEBUG: '; GC.start; puts 'DEBUG: '”);

ruby_finalize();

But what happens now is:

DEBUG: Bar::Bar()
DEBUG: get_new_bar
DEBUG:
DEBUG:
DEBUG: Bar::~Bar();

As soon as I call rb_protect() a second time with completely different
code, the object allocated in the previous rb_protect call will be
deleted
in the next GC run.

The question is: Why doesn’t the GC delete the Bar instance when I
create
it within rb_protect()? Is the Bar instance referenced by a global
variable somewhere? Are there any threading issues I should be aware of
with rb_protect()?

This only happens in Ruby 1.8.7. In 1.9.0 there is no difference between
the direct call and the rb_protect wrapped call.

Thx,

Tobias