[plt-scheme] Cooperating with the GC in foreign.ss code

From: Noel Welsh (noelwelsh at gmail.com)
Date: Wed Sep 9 05:31:56 EDT 2009

Hi all,

I'm wrapping a C struct that contains a pointer to a user allocated
block of memory. When a GC takes places, this pointer is changed to
point to a new location, but the values it points to are not copied to
that location. At least that is what I assume is taking place; the
observable effect is that the same values are not read back when
dereferencing the pointer. The example below illustrates the problem.
How should I fix this so that values survive across a GC? This is in; I'll upgrade if necessary.


#lang scheme

 (planet schematics/schemeunit:3))


(define _size_t _int)

(define-cstruct _gsl_matrix
  ([rows  _size_t]
   [cols  _size_t]
   [tda   _size_t]
   [data  _pointer]
   [block _pointer]
   [owner _int]))

(define (gsl_matrix-malloc r c)
  (define ptr (malloc _double (* r c)))
  (define m (make-gsl_matrix r c c ptr #f 0))

(define make-matrix gsl_matrix-malloc)

(define (matrix-ref m r c)
  (define rows (gsl_matrix-rows m))
  (define cols (gsl_matrix-cols m))
  (define idx (+ (* r cols) c))
  (ptr-ref (gsl_matrix-data m) _double idx))

(define (matrix-set! m r c val)
  (define rows (gsl_matrix-rows m))
  (define cols (gsl_matrix-cols m))
  (define idx (+ (* r cols) c))
  (ptr-set! (gsl_matrix-data m) _double idx val))

(define m (make-matrix 4 4))

;; Set an element to known value and check it has that value
(matrix-set! m 1 1 3.0)
(check-= (matrix-ref m 1 1) 3.0 0)

;; Do some work, necessitating a GC
(for ([i (in-range 10000)])
     (make-vector i))

;; See if the value survives across a GC (it shouldn't)
(check-= (matrix-ref m 1 1) 3.0 0)

Posted on the users mailing list.