[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Smobs & garbage collecting
Smobs & garbage collecting
Fri, 30 Dec 2005 21:20:14 +0100
Mozilla Thunderbird 1.0.7 (X11/20051019)
Currently hacking on http://www.gnu.org/software/liquidwar6/ I've had 2
problems with Guile and smobs. Hopefully the problems are solved and
I've found solutions which although not 100% satisfying have the merit
of "working". I'm just writing here to keep you informed of the
potential difficulties one might encounter, hopefully this could save
time for future hackers 8-)
First problem was with garbage collecting in general. It's hard to
extract a 10-line code snippet for what I want to describe, but here's
the description I can make:
First, you need to know I'm a little obsessed by memory leaks. So
obsessed that in my program I never call "malloc" directly. I always
call a macro which calls malloc of course, but also keeps a track of the
call to malloc. And I call the same kind of macro instead of "free". The
result is that at the end of my program, just before returning from
main(int, char **), I can check wether free has been called as many
times as malloc. This is a handy debugging tool I find, and I'm not
ready to give it up.
Things were going pretty well, when I started to implement my first
smob. Everything went smoothly, the docs on
are clear enough, very well. But... things went wrong when I started to
call "(display %a-global-pointing-to-my-current-smob)".
For "some reason", doing this had a strange side effect: whenever the
program exited, one smob was systematically left, and not garbaged
collected. I mean, the garbage collection generally works, I regularly
call code like:
(set! %lw6-menu-map (c-lw6map-read (assoc-ref x "path")))
%lw6-menu-map is a global variable, holding the "currently selected menu
map", c-lw6map-read is a function which returns an instance of my custom
Whenever I call this, the previous smob stored in %lw6-menu-map is freed
(I verified this with debug traces). I force scm_gc() regularly, to
avoid keeping too many useless smobs in memory.
But... when I'm done with Guile, done with everything, ready to exit
main(), there's still, and always, one smob. Doing things like (set!
%lw6-menu-map #f) doesn't help. Calling scm_gc() dozens of time,
sleeping between calls, trying to allocate memory with scm_must_malloc
change nothing to it: there's one, only one, one single smob left.
You might say, who cares? When main() will exit, memory will be freed
anyways... Point is it wrecks all my "count mallocs and frees" strategy,
and my program started to complain systematically about memory leaking.
The funny thing is that if I stop calling (display %my-smob) then all
the smobs are correctly freed when calling scm_gc().
The ultimate workarround I found is to keep myself a track of all my
allocated smobs, in parallel of what Guile does, and free this nasty
smob myself, no matter what Guile thinks of it, at this stage the Guile
session is over anyways...
This leads to two remarks:
1) I think calling scm_gc() should actually *all* the smobs 8-)
2) I also really lacked the "opposite of scm_init_guile". Something that
frees everything that could have been set up by Guile.
Now, when this was done, I started to have "other problems" with my
code. Basically sometimes when garbage collection happened, the program
aborted. Just "Aborted" on the console, and that's it. Sad.
Backtracing with gdb told me it was in scm_gc().
I found out that the problem disappeared when I decided to make my free
callback (the one set up with scm_set_smob_free) return systematically a
value of 0. I understand the return value of this function should
reflect the amount of freed memory and be a hint for Guile to optimize
memory management. Point is I do not use scm_must_malloc to allocate
memory and Guile doesn't know when I allocate memory.
It's a design option of my program to have independent chunk of codes
(libraries in fact) which are absolutely not aware that they are used in
a Guile context, so allocating memory with scm_must_malloc does not
really make sense for them. In fact it's not even acceptable, one could
wish to use these objects without using Guile at all.
So well, returning 0 is just fine, fixes the problem, very well for me.
I just think it could be worth mentionning in the docs that the returned
value for the free callback should reflect the amount of memory freed
that was *allocated with scm_must_malloc* and not the general amount of
Or maybe I'm wrong on this point, in that case I'd be curious to hear
the advices of Guile experts 8-)
Christian Mauduit <address@hidden> __/\__ ___
\~/ ~/(`_ \ ___
http://www.ufoot.org/ /_o _\ \ \_/ _ \_
http://www.ufoot.org/ufoot.pub (GnuPG) \/ \___/ \__)
- Smobs & garbage collecting,
Christian Mauduit <=