[cairo] Memory leaks in cairomm

Rodrigo Rivas rodrigorivascosta at gmail.com
Mon Jun 12 07:41:37 PDT 2006


I don't know if I'm missing something, but I've noted that the RefPtr
implementation in cairomm leaks memory "always".
That is because when you call, say Surface::create(...), it calls
basically "new Surface(cairo_surface_create_linear(...))" and returns
the new pointer wrapped into a RefPtr<Surface>. The ~RefPtr decrements
the ref-counter of the cairo_surface_t object, but it <never> deletes
the new'ed Surface object. It's same for every type in cairomm.
The glibmm's RefPtr doesn't leak! But that's because the
Glib::ObjectBase class takes care of this, and gets notified when the
wrapped object is destroyed.
Also there are a few Glib classes that doesn't inherit from
Glib::ObjectBase, such as Glib::Thread. Those are implemented simple
as cast pointers to the underlying type (I'm not sure this is 100%
portable, valid C++ code, but it will probably work as long as there
is no virtual functions and no member variables).

I've taken this last technique and it looks like this:

class Surface
{
private:  // no create, no copy, no destroy
  Surface();
  Surface(const Surface&);
  void operator=(const Surface&);
  ~Surface();

public:
  typedef cairo_surface_t cobject;
  static RefPtr<Surface> wrap(cobject *obj)
  {
    Surface *obj = reinterpret_cast<Surface*>(obj);
    RefPtr<Surface> ptr(obj);
    check_object_status_and_throw_exception(*obj);
    return ptr;
  }

  static RefPtr<Surface> create(const RefPtr<Surface> other, Content
content, int width, int height)
  {
    cairo_surface_t* cobject = cairo_surface_create_similar(other->cobj(),
                       (cairo_content_t)content, width, height);
    check_status_and_throw_exception(cairo_surface_status(cobject));
    return wrap(cobject);
  }
  cobject* cobj() { return reinterpret_cast<cobject*>(this); }
  cobject* cobj() const { return
const_cast<cobject*>(reinterpret_cast<const cobject*>(this)); } // it
is nonsense to return a const cobject* here

   // the rest of the class is the same
};


Now, you'll just need to make the same change on ALL the wrapping classes.

Best regards.
Rodrigo.


More information about the cairo mailing list