From: nerochiaro <ner...@gm...> - 2006-03-08 01:02:48
|
I was reading the SWIG docs about Ruby's memory management issues, where %trackobjects & friends are explained. But there's either something i don't understand or something I'm missing. Let's say that my C++ object looks something like this (class Tag is fully defined elsewhere): class Tag; class File { =09private: =09=09Tag* mtag; =09public: =09=09File() { mtag =3D new Tag(); } =09=09~File() { delete mtag; } =09=09Tag* getTag() { return mtag; } }; I wrap these classes with SWIG. My understanding is that I need to enable %trackobjects on the Tag class, to prevent each call to File#getTag to return a different Ruby object_id when the actual C++ Tag instance returned is always the same. Now, reading the documentation it seems to me that once i enable %trackobjects on Tag, I have also to define a %markfunc on File. This %markfunc tells the Ruby GC that the Tag object returned by getTag is still reachable from instances of File and shall not garbage collected. I define it like this: static void SWIG_Mark_File(void* ptr) { =09File* file =3D (File*) ptr; =09VALUE object =3D SWIG_RubyInstanceFor((void*)file->getTag()); =09if (object !=3D Qnil) rb_gc_mark(object); } So far so good. But I found that there was something more that was necessary and that doesn't seem mentioned in the docs: one also needs to define a custom %freefunc on the File object with something that looks like this: static void SWIG_Free_File(File *arg1) { =09SWIG_RubyRemoveTracking(arg1); =09 =09Tag* tag =3D arg1->getTag(); =09SWIG_RubyRemoveTracking(tag); =09delete arg1; } In other words, one is appearently responsible to remove the object trackings for all the reachable (and tracked) objects when the "root" object is getting finalized. Failure to do so resulted, in my case, in a segfault later on in the program, when ruby decided to start recycling object_ids and picked one that SWIG was still tracking to a now defunct C++ object. Just a couple of questions: First: is my understanding correct so far ? Second: am I just distracted and didn't find it, or is this not yet documented in the manual ? Thank you. |