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 <[EMAIL PROTECTED]> __/\__ ___ \~/ ~/(`_ \ ___ http://www.ufoot.org/ /_o _\ \ \_/ _ \_ http://www.ufoot.org/ufoot.pub (GnuPG) \/ \___/ \__) _______________________________________________ Guile-user mailing list [email protected] http://lists.gnu.org/mailman/listinfo/guile-user
