[gambit-list] How allocate u8vectors from C safely&without memory leaks? (Noted ___EXT(___alloc_scmobj)(___sU8VECTOR, len, ___MOVABLE0) leaks 100%, that's used by the sqlite ffi etc.)

Mikael mikael.rcv at gmail.com
Sun Jun 16 07:06:05 EDT 2013

Dear Marc,

Just realized there's a memory leak in many Gambit libraries, such as the
sqlite FFI - their u8vector allocation in C boils down to:

___result = ___EXT(___alloc_scmobj)(___sU8VECTOR,len,___MOVABLE0);

Studying ##make-u8vector of _kernel.scm provides some inspiration: It

 1) Shows that it's fine to use ___STILL

 2) Uses  ___still_obj_refcount_dec ,

 3) Has its C code in a ##c-code and not a ##c-lambda

 4) Has its surrounding Scheme code in (##declare (not interrupts-enabled))

 5) Surrounds the ___alloc_scmobj call by some magic (

(##make-u8vector provides a code path for small objects apart from this,
though the use regarded here should be for u8vectors of nontrivial size so
going with the codepath for large objects should always be fine.)

By applying 1) and 2) I get something that works but can't know if it's
really correct and safe:

How do you allocate an u8vector in C code in a way that does not leak
memory, and that safely transfers the new object reference from the C world
to the Scheme world?


*How to reproduce*
Running a test that repeats

((c-lambda () scheme-object "___result =

over and over e.g.

(##gc-report-set! #t)
(for-each (lambda (x) ((c-lambda () scheme-object "___result =
          (string->list (make-string 100000))

shows that this memory leaks all the allocated memory (!).

*Fix, duno if safe & complete*

(##gc-report-set! #t)
(for-each (lambda (x) ((c-lambda () scheme-object "___result =
(!___FIXNUMP(___result)) ___still_obj_refcount_dec (___result);
          (string->list (make-string 100000))

*Copy of ##make-u8vector of _kernel.scm for reference*

(define-prim (##make-u8vector k #!optional (fill (macro-absent-obj)))
  (##declare (not interrupts-enabled))
  (let ((v (##c-code #<<end-of-code

long i;
long n = ___INT(___ARG1);
long words = ___WORDS(n) + 1;
___SCMOBJ result;
if (n > ___CAST(___WORD, ___LMASK>>___LF))
  result = ___FIX(___HEAP_OVERFLOW_ERR); /* requested object is too big! */
else if (words > ___MSECTION_BIGGEST)
    result = ___alloc_scmobj (___sU8VECTOR, n, ___STILL);
    if (!___FIXNUMP(result))
      ___still_obj_refcount_dec (result);
    ___BOOL overflow = 0;
    ___hp += words;
    if (___hp > ___ps->heap_limit)
        overflow = ___heap_limit () && ___garbage_collect (0);
      ___hp -= words;
    if (overflow)
      result = ___FIX(___HEAP_OVERFLOW_ERR);
        result = ___TAG(___hp, ___tSUBTYPED);
        ___HEADER(result) = ___MAKE_HD_BYTES(n, ___sU8VECTOR);
        ___hp += words;
if (!___FIXNUMP(result) && ___ARG2 != ___ABSENT)
    for (i=0; i<n; i++)
___RESULT = result;


    (if (##fixnum? v)
        (##make-u8vector k fill))
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20130616/1aca7a5b/attachment.htm>

More information about the Gambit-list mailing list