The make-fresh-user-module procedure leaks memory in guile-2.0.11 as demonstrated by the attached test case. This test case should be invoked either with the "shared" or "fresh" option. If invoked with the "fresh" option, it will call make-fresh-user-module on each iteration through the loop. On my 32-bit machine it will steadily accumulate a memory leak before running out of memory on consuming approximately 2.2G memory, after about 180,000 iterations. If called with the "shared" option, it will accumulate no additional memory while executing, and will execute normally to the end of its iterations.
The question which might be asked is "Would any sane person ever want to invoke the make-fresh-user-module procedure more than a few times in a practical program?". The answer to this question is "Yes", if guile is being used as an extension framework for a C or C++ program, and it executes guile extensions as individual tasks, and it is necessary that top levels should not to be shared. The execution of tasks concurrently is one such case, but there can be many cases where isolated top levels are desirable for tasks executed serially also. Test case: ----------------------------- snip ----------------------------- /* compile with 'gcc -O2 -Wall `pkg-config --cflags --libs guile-2.0` -o test-guile' */ #include <unistd.h> #include <libguile.h> #include <stdio.h> #include <string.h> int fresh; void* func (void* data) { switch (fresh) { case 0: scm_c_eval_string(""); break; default: scm_c_eval_string("(set-current-module (make-fresh-user-module))"); } return NULL; } int main (int argc, char *argv[]) { int count; if (argc != 2 || (strcmp (argv[1], "shared") && strcmp (argv[1], "fresh"))) { puts ("Usage: test-guile shared | fresh"); exit (1); } if (!strcmp (argv[1], "fresh")) { puts("Invoking make-fresh-user-module"); fresh = 1; } else puts("Using shared top level"); for (count = 0; count < 256000; ++count) { scm_with_guile(func, NULL); if (!(count % 100)) { printf("%d ", count); fflush(stdout); } usleep(1); } puts(""); return 0; }