Debugging reference counting in GNOME C++ bindings with GDB

Overview

For the last couple days I’ve been tracking down some reference counting problems in cluttermm. In the course of this I’ve been working on figuring out how GDB can help me do this. Here is what I’ve come up with. If you have improvements please let me know.

Watching the reference count variable

The first small obstacle is that pretty much all objects are wrapped in a RefPtr, glibmm‘s reference-counting shared smartpointers. This is a good thing and gdb makes accessing the underlying C++ object pretty painless. The following command demonstrates this.

p alpha.pCppObject_

For this example I’m using the alpha variable of type Glib::RefPtr<Clutter::Alpha>. In this command we used the fact that gdb gives you access to any member of a class, whether public or private. You should have gotten output similar to the following.

$1 = (Clutter::Alpha *) 0x9cfe40

Now the interesting part. We want to detect any changes in the ref_count variable. To do this we need to watch the ref_count field. The following command does this.

watch alpha.pCppObject_->gobject_->ref_count

To make this a bit more convenient, I’ve used the gdb define command to create a shortcut. Here is an example session.

(gdb) define watchRefCnt
Type commands for definition of "watchRefCnt".
End with a line saying just "end".
>watch ($arg0).pCppObject_->gobject_->ref_count
>end

Now you just need to use the shortcut like this.

watchRefCnt alpha

Which should give you a confirmation similar to the following.

Hardware watchpoint 2: (alpha).pCppObject_->gobject_->ref_count

The obvious thing to do next is to place this command in a .gdbinit file so that it can be pulled in automatically.

Breaking on last unreference

One of things I was most interested in catching was when the g_object_unref function was called with the condition that the _object pointer was equal to a certian pointer and the ref_count variable == 1. This would indicate that the object is ready to be disposed. To do this we first need to get the address of the underlying GObject like this.

(gdb) p alpha.pCppObject_->gobject_
$3 = (GObject *) 0x9c91e0

You now have a convenience variable, $3, which you can use in the conditions. You then need to set a breakpoint on g_object_unref and set the conditions like this.

b g_object_unref
cond 4 _object==$3&&((GObject*)$3)->ref_count==1

This, of course, would also be nice as a custom command. I’ll leave that as an exercise for the reader. ;)

Future explorations

I forsee future blog entries along these lines so stay tuned. There are quite a few things that interest me in gdb right now.

The Archer project is quickly improving C++ support in gdb. I’ve been using gdb 7.2 for my debugging as I wanted to have a stable debugging platform with all the new C++ enhancements. They have a git repository for those who want the bleeding edge.

Python scripting has been available in gdb since 7.0. I plan on looking into this as a way of streamlining debugging tasks and honing my Python skills which are pretty rusty.

Please let me know if you see any areas for improvement.

Tweets for week ending 2010-09-19

  • Openismus day 76: murrayc showed me the proper way to fix cluttermm bug. Committed fix for that and a few other issues. http://ur1.ca/1o8sp #
  • Openismus day 75: Found the problem with cluttermm. Clutter::Alpha::get_timeline() was the culprit. Came up with a fix that worked. #
  • Openismus day 74: Went thru clutter code to see what tutorial program is doing. emacs+gdb+gtags (GNU Global) is nice for this. More gdb too. #
  • Openismus day 73: Took a bit of a detour to go deeper into gdb. Think I've pretty much gone though the entire manual. Back to cluttermm bug. #
  • Openismus day 72: Struggling with the bug in cluttermm. Maybe I should first understand what the clutter c code is doing. ;) #
  • Openismus day 71: Learned to use gdb to debug reference counting issues in GObject-based code. http://ur1.ca/1lrpi & comments were helpful. #

Tweets for week ending 2010-09-12

  • Openismus day 70: Looking into ref count issues in cluttermm. Grokking refs in *mm/glib. Doc patch committed in clutter. http://ur1.ca/1kpji #
  • Openismus day 69: Working on getting effects example in cluttermm_tutorial working. Found a few other examples are broken. Looking on it. #
  • Openismus day 68: Got cluttermm compiling & commited changes. http://ur1.ca/1jr3k Then fixed dumb std::vector issue. http://ur1.ca/1jr3x :-# #
  • Openismus day 67: Trudged through compile issues while removing *Handle containers in cluttermm. Started using emacs yasnippet module. #
  • Openismus day 66: Learnt enough Perl to read some of the *mm binding generation code. Workd on removing *Handle usage in cluttermm. #

Tweets for week ending 2010-09-05

  • Openismus day 65: With murrayc's help, found fix for cluttermm_tutorial segfault. Requires going deeper into *mm bindings. Will commit soon. #
  • Openismus day 64: tbf helped try to find cause of segfault in cluttermm_tutorial. Still couldn't fix it. :( Learnt some advanced gdb stuff. #
  • Openismus day 63: Think I fixed yesterday's bug. cluttermm-tutorial still segfaults a few lines later, though. Got GNOME git commit access! #
  • Openismus day 62: Looked through lots of *mm libraries to get an idea of how things are really done. Tracked down another bug in cluttermm. #
  • Openismus day 61: Finished up *mm wrapping tutorial, fixed small bug in cluttermm that broke cluttermm turorial. http://www.ur1.ca/1ecom #

Tweets for week ending 2010-08-29

  • Openismus day 60: Learning M4 as it seems useful for autotools and C++/*mm bindings. ION, BBQ at Openismus office on Friday 27th, August. #
  • Openismus day 59: Looking into cluttermm_tutorial problems which is leading me into learning more C++-binding stuff, which is fine with me. #
  • Openismus day 58: Got cluttermm building in jhbuild by adding atkmm dependency. Had to use gtkmm's gtkmm-2.22 branch. Needs 2.24 branch? #
  • Openismus day 57: Started porting gmemory to use gtkmm. Got autotools stuff converted. Couple minor issues with jhbuild and *mm stuff. #
  • Openismus day 56: Got emacs configured nicely now. Dropped CEDET for now. Currently using autocompletion, xcscope gccsense, flymake. #
  • Openismus day 55: My look into gmmproc turned into me spending more time setting up emacs. Issues getting semantic to find system libs. #

Tweets for week ending 2010-08-22

  • Openismus day 54: Rereading the gmmproc documentation slowly. Doing the example is good excuse to reacquaint myself with Emacs. #
  • Openismus day 53: Committed code for glib-mkenums changes. Began looking into updating cluttermm. Gotta learn to wrap libs sooner or later. #
  • Openismus day 52: Learned about glib-mkenums and implemented most needed changes. Remember emums != enums :( . Finished http://is.gd/efGXH. #

Tweets for week ending 2010-08-15

  • Openismus day 51: Mostly distracted by Andre's beautiful pony tail and conservative rhetoric. A little secret about Andre.. He eats tofu. :P #
  • Openismus day 50: 50 days at Openismus. Woot! Started looking into glib-mkenums. Read half of http://is.gd/efGXH. Other stuff I forget. ;) #
  • Openismus day 49: After problems with clutter-gtk on Fedora, I decided to install Ubuntu. Reran Valgrind. Now I get no definite leaks. Hmm?! #
  • Openismus day 48: More memory leak analysis w/ Valgrind. Mentioned some definite leaks that I can't seem to find. Did fix a few, though. #
  • Openismus day 48: #
  • Openismus day 47: After taking care of some paper work, I started using Valgrind's Memcheck tool to find leaks in gmemory. #

New Flat and the Internet Gap

We slept in the new flat for the first time last night. As usual, at least in Germany, it’s going to take a few weeks to get DSL connected. In our case, DSL gets connected on the 30th. This used to be the time when I’d fall into a deep depression due to withdrawal issues. However, this time is different.

For the time being I’m using the awesome new feature in Android 2.2 for sharing a mobile internet connection. Impressed with how easy it is to set up. It’s as easy as turning the feature on and setting the access point name and passphrase. Once that’s done up to 8 computers can connect as they would to any wireless access point.

Unfortunately, my mobile data plan only allows up to 200MB at 3G speed after which it gets throttled down to GPRS speeds. But it’s better than nothing and once DSL is finally connected we’ll be rewarded with 50Mbits down and 10Mbits up. That’s about 8-9 faster than what we had in San Diego for only a little more money.

Tweets for week ending 2010-08-08

  • Openismus day 46: Finished autoconf changes to fix install issues in gmemory. Bungled first push. Commit here: http://bit.ly/cRpibS #
  • Openismus day 45: Back to work after 2 days of moving into new flat. Started cleaning up autoconf problems. Added –enable-warnings flag. #
  • Openismus day 40-44: GUADEC! #

Introducing GMemory v0.1

For the last few weeks I’ve been working on a small concentration game called GMemory. This was done as a part of the Openismus trainee program.

Update: See below.

For those not familiar with the game Concentration, or Memory as I grew up knowing it, the basic idea is that one has a number of matching card pairs turned face down. The player(s) then attempt(s) to match these pairs by turning over two cards. If the cards match those two cards remain face up. Otherwise, the cards are returned to the face down position. This is repeated until all cards are face up. Here’s a screencast of GMemory being played.

As you can hopefully see, GMemory is currently in a playable state and it actual quite enjoyable if you’re into these types of games. However, there is a lot more to do to reach what I’d consider a 1.0 release. Besides some code reworking and some known bugs, I’d like to see a score tracker, multi-player mode, card animation and selectable themes.

The game is written in C using GTK+, GObject, Clutter and Cairo. In the course of writing GMemory I ran into a few bugs in clutter-gtk. The first bug was that no events were being received when using the embedded clutter gtk widget. You can find the bug report here. The second major bug I ran into was that once I got a version combination that gave me events, I always received double the events that I expected. This is a known bug and I’ve got a work around in the code for that.

There are also a number of known bugs. As you may have noticed from the screencast, the last card of the last successful match does not get shown before the statistics dialog box pops up. It seems the dialog blocks the drawing even thought the function to draw the card is called before the call to show the dialog box. Another bug is that once the game is over the playing area does not resize when the window is resized. I’ll tackle this once I’ve reworked the code some.

You can find GMemory’s git repository at Gitorious and the tarball can be had here.

Unfortunately, right now I’m building against the master branches of clutter and clutter-gtk. Expect breakage.

Btw, I'm attending GUADEC right now.

Update: After trying this on Ubuntu Lucid, I experienced none of the event-related problems with clutter-gtk. This seems to be Fedora 13 specific. Thus, I’ve removed the workaround for the double event issue and changed the configure.ac file to rely on the clutter and clutter-gtk versions shipped with Ubuntu Lucid. The new tarball is here.