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