<div dir="ltr"><br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra">
<div class="gmail_quote"><div class="im"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div class="gmail_extra"><div class="gmail_quote">
<div>


<br></div><div>> (define o (get-foreign-wrapper ...))  ; a will has been created for o, which will delete the underlying C data<br></div><div>> (define t (make-table weak-values: #t))<br></div><div>> (table-set! t 'o o)<br>



</div><div>> (set! o #f)<br></div><div>> (##gc)<br><br></div><div>At this point your foreign wrapper is not strongly reachable anymore.  The garbage collection has triggered your will, which has freed the C object wrapped by o.  But you can still<br>



<br></div><div>> (println (table-ref t 'o))<br><br></div><div>And get an access to invalid memory or a segmentation fault.<br></div></div></div></div></div></blockquote><div><br></div></div><div>Wait, what is returned by <span style="font-family:arial,sans-serif;font-size:13px">get-foreign-wrapper and are other references to it sticking around at that GC?</span></div>
</div></div></div></blockquote><div><br></div><div>get-foreign-wrapper creates a foreign object with type (struct "something") and attachs a will to it that calls (e.g.) foreign-release! on it when executed.  A complete, working example follows:<br>
<br>; test-invalid-access.scm<br>;<br>; Compile with<br>;<br>; gsc -cc-options -g -exe test-invalid-access.scm<br>;<br>; Test with<br>;<br>; valgrind ./test-invalid-access<br>; <br></div><div>; (Or some other memory usage checker.)<br>
</div><div>;<br>; Comment out last line to see that the program would otherwise never access <br>; invalid memory.<br><br>; BEGIN Library code<br><br>(c-declare "struct point {int x; int y;};")<br><br>(define (make-point x y)<br>
  (let ((p ((c-lambda (int int)<br>                      (struct "point")<br>              "struct point *p = (struct point*)___EXT(___alloc_rc)(sizeof(struct point));<br>               p->x = ___arg1;<br>
               p->y = ___arg2;<br>               ___result_voidstar = p;")<br>            x<br>            y)))<br>    (make-will p<br>               (lambda (x)<br>                 (println "releasing " (point->string x))<br>
                 (foreign-release! x)))<br>    p))<br><br>(define point-x<br>  (c-lambda ((struct "point"))<br>            int<br>    "___result = ((struct point*)___arg1_voidstar)->x;"))<br><br>(define point-y<br>
  (c-lambda ((struct "point"))<br>            int<br>    "___result = ((struct point*)___arg1_voidstar)->y;"))<br><br>(define (point->string p)<br>  (string-append "point("<br>                 (number->string (point-x p))<br>
                 ", "<br>                 (number->string (point-y p))<br>                 ")"))<br><br>; END library code; BEGIN user code<br><br>(define p (make-point 1 2))<br>(define t (make-table weak-values: #t))<br>
(table-set! t 'p p)<br>(println "before releasing: " (point->string p))<br>(set! p #f)<br>(##gc)<br>(println "after releasing:")<br>; Comment out the following line and you get no invalid accesses.<br>
(println (point->string (table-ref t 'p)))<br><br></div><div>; END of example<br></div></div></div></div>