mrb_gc_register and mrb_gc_unregister make managing mruby objects on C side much easier. However, there is a problem if you call mrb_gc_register multiple times for the same object. The first call to mrb_gc_unregister will remove all registrations for this object.
I wrote a program illustrating this issue. Here we call a C function with two arguments, keeping only one of them from being collected. But if both arguments are actually the same object, the program will crash.
#include <mruby.h>
#include <mruby/proc.h>
#include <mruby/class.h>
mrb_value test;
mrb_value foo(mrb_state * mrb, mrb_value self)
{
mrb_value a, b;
mrb_get_args(mrb, "oo", &a, &b);
mrb_gc_register(mrb, a);
mrb_gc_register(mrb, b);
// do something with a & b
// a is no longer needed
mrb_gc_unregister(mrb, a); // without this line the program will run correctly
// only b will be kept
test = b;
return mrb_nil_value();
}
int main()
{
mrb_state * mrb = mrb_open();
RProc * proc = mrb_proc_new_cfunc(mrb, foo);
mrb_define_method_raw(mrb, mrb->object_class, mrb_intern_cstr(mrb, "foo"), proc);
mrb_load_string(mrb, "tap do ar = [1,2,3]; foo(ar, ar) end");
mrb_garbage_collect(mrb);
mrb_value state = mrb_funcall(mrb, test, "inspect", 0);
mrb_funcall(mrb, mrb_top_self(mrb), "puts", 1, state);
mrb_gc_unregister(mrb, test);
mrb_close(mrb);
}
In theory I could ensure on C side that mrb_gc_register is only called once per object, but this is not as simple in general case.
So, could we modify behavior of mrb_gc_unregister so that it removes only one registration? Then it would be user responsibility to call mrb_gc_register and mrb_gc_unregister an equal number of times.
The text was updated successfully, but these errors were encountered:
mrb_gc_register
andmrb_gc_unregister
make managing mruby objects on C side much easier. However, there is a problem if you callmrb_gc_register
multiple times for the same object. The first call tomrb_gc_unregister
will remove all registrations for this object.I wrote a program illustrating this issue. Here we call a C function with two arguments, keeping only one of them from being collected. But if both arguments are actually the same object, the program will crash.
In theory I could ensure on C side that
mrb_gc_register
is only called once per object, but this is not as simple in general case.So, could we modify behavior of
mrb_gc_unregister
so that it removes only one registration? Then it would be user responsibility to callmrb_gc_register
andmrb_gc_unregister
an equal number of times.The text was updated successfully, but these errors were encountered: