GNOME Bugzilla – Bug 606357
Crash on exit if using canvas items derived from Goocanvas::ItemSimple
Last modified: 2011-06-13 13:24:11 UTC
When I create a canvas item derived from GooCanvas::ItemSimple, my application crashes with a segmentation violation on exit (or whenever I try to clear the custom items canvas). This crash does not occur if my object is derived from Goocanvas::Rect or Goocanvas::Ellipse. I see exactly the same behavior in the custom_item example app from GooCanvas 0.14.0 (which I used as the pattern for my custom item). The GooCanvas 0.15.1 source tarball does not appear to have an examples folder anymore. The stack trace from the crash of the 0.14.0 custom_item example is as follows:
+ Trace 219958
As you can see, the above indicates that the seg fault is occurring in Goocanvas::Item::set_cancel_vfunc(). The source code for that function is as follows: void Goocanvas::Item::set_canvas_vfunc(Canvas* canvas) { BaseClassType *const base = static_cast<BaseClassType*>( g_type_interface_peek_parent( // Get the parent interface of the interface (The original underlying C interface). g_type_interface_peek(G_OBJECT_GET_CLASS(gobject_), CppObjectType::get_type()) // Get the interface. ) ); if(base && base->set_canvas) (*base->set_canvas)(gobj(),(canvas)->gobj()); } As you can see from this source code, if set_canvas_vfunc is called with a NULL canvas pointer, then a seg fault will occur at the last line. This appears to be what is happening. If I extend my CustomItem class with its own set_canvas_vfunc() method which only calls Goocanvas::Item::set_canvas_item() if the Canvas* is non-NULL, my app does not crash. While this *seems* to be an adequate workaround, it does not appear to be the way that other Goocanvas Items avoid this crash... Goocanvas::Rect, for example, does not have its own set_canvas_vfunc() method which filters out NULL canvas pointers. I don't know if there are any negative consequences for the above workaround. I defer to those more familiar with the Goocanvas design for the answer to that. But I did want to report what I'd found. Thanks in advance for any feedback you can provide.
Created attachment 188889 [details] [review] patch: Make 0 pointer conversion from Goocanvas::Canvas* to GooCanvas* work. This patch fixes the bug, I believe. I've tested with the custom_item example in goocanvasmm. The solution is to change the conversion from Goocanvas::Canvas* to GooCanvas* that gmmproc uses when it generates .h and .cc files out of .hg and .ccg files. The solution uses Glib::unwrap(canvas), which tests if the argument is 0. The changes in the generated source code are diff goocanvasmm-org/item.cc goocanvasmm/item.cc 1220c1220 < return (obj->get_canvas_vfunc())->gobj(); --- > return Glib::unwrap(obj->get_canvas_vfunc()); 2888c2888 < goo_canvas_item_set_canvas(gobj(), (canvas)->gobj()); --- > goo_canvas_item_set_canvas(gobj(), Glib::unwrap(canvas)); 3610c3610 < (*base->set_canvas)(gobj(),(canvas)->gobj()); --- > (*base->set_canvas)(gobj(),Glib::unwrap(canvas)); diff goocanvasmm-org/itemmodel.cc goocanvasmm/itemmodel.cc 1779c1779 < return Glib::wrap((*base->create_item)(gobj(),(canvas)->gobj()), false); --- > return Glib::wrap((*base->create_item)(gobj(),Glib::unwrap(canvas)), false); I'm not very familiar with the goocanvas and goocanvasmm modules, but I don't see any possible drawback with this solution. Perhaps someone more familiar with the modules can confirm.
I have pushed the patch (with a small difference in ChangeLog). No one has objected to comment 1, and I'm convinced that this fix is correct. This bug has inspired the gtkmm-list message http://mail.gnome.org/archives/gtkmm-list/2011-June/msg00011.html "Are vtables of interfaces always correctly initialized?"
It looks good. Thanks.