Handling GC allocated objects in C As part of an effort to improve our GC, we need to keep track precisely of where objects are stored, so we can incrementally move from the current conservative GC to a more advanced precise and moving GC. Previously, all global C variables were considered GC roots, but this makes the GC less efficient and increases the chances false references are found to GC memory, hence retaining more memory than needed. We need to tell the GC that some object is supposed to be kept alive as if it was referenced in a global variable. For Mono embedders ------------------ In C#, if you say: class T { static object o; } Any object which is stored in `o' is considered to be alive -- it will not be collected. `o' is a member of the root set for the GC. However, in C code, this is not the case. If you have: static MonoObject* o = NULL; The object in `o' will *NOT* be scanned. If you need to store an object in a C variable and prevent it from being collected, you need to acquire a GC handle for it. guint32 handle = mono_gchandle_new (my_object, TRUE); TRUE means the object will be pinned, so it won't move in memory when we'll use a moving GC. You can access the MonoObject* referenced by a handle with: MonoObject* obj = mono_gchandle_get_target (handle); When you don't need the handle anymore you need to call: mono_gchandle_free (handle); Note that if you assign a new object to the C var, you need to get a new handle, it's not enough to store a new object in the C var. So code that looked like this: static MonoObject* o = NULL; ... o = mono_object_new (...); /* use o */ ... /* when done to allow the GC to collect o */ o = NULL; should now be changed to: static guint32 o_handle; ... MonoObject *o = mono_object_new (...); o_handle = mono_gchandle_new (o, TRUE); /* use o or mono_gchandle_get_target (o_handle) */ ... /* when done to allow the GC to collect o */ mono_gchandle_free (o_handle); For Mono runtime developers --------------------------- There are two kinds of static vars used to store pointers to GC memory that we need to consider: *) objects *) other memory chunks allocated with GC_MALLOC(). Objects should be dealt with the GC handle support as detailed above. Other items should register the static pointer as an area to be considered part of the root set with the following: static gpointer my_gc_data = NULL; ... MONO_GC_REGISTER_ROOT (my_gc_data); my_gc_data = GC_MALLOC (...); Note that this registration is not necessary for *LOCAL* variables, as they are stored on the stack. It is only necessary for global variables, as they are not a part of the GC's root set. Once you have done the MONO_GC_REGISTER_ROOT, the variable is just like a static variable in C#. To keep an object alive, you have the variable reference the GC memory, to remove the reference, set the variable to NULL. As we prepare the code for a precise GC, GC_MALLOC () will not be used anymore in this way in most cases: we'll have a mechanism to specify exactly where references to GC memory is stored. This mechanism is now available with the new GC, see usages of mono_gc_alloc_fixed (), mono_gc_register_root () and mono_gc_make_descr_from_bitmap(). See also docs/precise-gc for additional info.