unofficial mirror of guile-user@gnu.org 
 help / color / mirror / Atom feed
* Smobs & garbage collecting
@ 2005-12-30 20:20 Christian Mauduit
  2005-12-31  0:32 ` Han-Wen Nienhuys
  2006-01-01 20:16 ` Stephen Compall
  0 siblings, 2 replies; 6+ messages in thread
From: Christian Mauduit @ 2005-12-30 20:20 UTC (permalink / raw)


Hi all,

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
-------------

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
http://www.gnu.org/software/guile/docs/guile-ref/Defining-New-Types--Smobs-.html
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
smob.

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.

Second problem
--------------

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
freed memory.

Or maybe I'm wrong on this point, in that case I'd be curious to hear
the advices of Guile experts 8-)

Happy hacking,

Christian.

-- 
Christian Mauduit <ufoot@ufoot.org>     __/\__ ___
                                        \~/ ~/(`_ \   ___
http://www.ufoot.org/                   /_o _\   \ \_/ _ \_
http://www.ufoot.org/ufoot.pub (GnuPG)    \/      \___/ \__)


_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user


^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2006-01-07 23:00 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-12-30 20:20 Smobs & garbage collecting Christian Mauduit
2005-12-31  0:32 ` Han-Wen Nienhuys
2005-12-31  9:02   ` Christian Mauduit
2006-01-03 10:40   ` Ludovic Courtès
2006-01-07 23:00     ` Neil Jerram
2006-01-01 20:16 ` Stephen Compall

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).