[gambit-list] How to properly allocate foreign object?

Marc Feeley feeley at iro.umontreal.ca
Fri Apr 10 15:49:15 EDT 2020


There are a few issues with your code.  First of all, you should use “___return(…);” to return a result (the assignment to ___result_voidstar is deprecated).  When Scheme code receives a foreign pointer, there is no “automatic freeing” of the memory done by Gambit.  You need to program that explicitly, for example using a will.  An alternative would be to create your own type with a release function, but that is probably overkill in this situation.  Here’s how I would write the code:

  (c-declare "#include <stdlib.h>")
  (c-declare "#include <sys/socket.h>")

  (c-define-type sockaddr_storage (struct "sockaddr_storage"))
  (c-define-type socket-address (pointer sockaddr_storage socket-address))

  (define alloc-socket-address
    (c-lambda ()
              socket-address
      "___return(malloc(sizeof(struct sockaddr_storage)));"))

  (define free-socket-address
    (c-lambda (socket-address)
              void
      "free(___arg1);"))

  (define (make-socket-address)
    (let ((sa (alloc-socket-address)))
      (if sa
          (make-will sa (lambda (sa)
                          (pp (list 'freeing sa))
                          (free-socket-address sa))))
      sa))

  (println "-----------")
  (pp (make-socket-address))
  (define foo (make-socket-address))
  (pp foo)
  (println "-----------")
  (##gc)
  (println "-----------")
  (pp (make-socket-address))
  (println "-----------")
  (##gc)
  (println "-----------")

  ;; prints:
  ;;
  ;; -----------
  ;; #<socket-address #2 0x7fe723405010>
  ;; #<socket-address #3 0x7fe7234050f0>
  ;; -----------
  ;; (freeing #<socket-address #2 0x7fe723405010>)
  ;; -----------
  ;; #<socket-address #4 0x7fe723405010>
  ;; -----------
  ;; (freeing #<socket-address #4 0x7fe723405010>)
  ;; -----------

Marc



> On Apr 10, 2020, at 3:12 PM, Jörg F. Wittenberger <Joerg.Wittenberger at softeyes.net> wrote:
> 
> Hi,
> 
> I'm afraid I don't grock the documentation wrt. memory management of
> foreign bjects.
> 
>> I really need a unix domain socket.  Actually an abstract socket on
>> Linux.
> 
> The example at at hand: a `struct sockaddr_storage`.  That is, in
> general, any kind of C struct to allocate.
> 
> Likely I'm doing it all wrong.  My great excuse(TM): I learned gambit's
> FFI from `gamsock` while adding domain socket support.  No, Mam, it's
> not been me. ;-)
> 
> # Part I, the easy thing
> 
> (c-define-type socket-address 
> (pointer (struct "sockaddr_storage") socket-address))
> 
> (c-lambda
> (...) socket-address
> "...
>  ___result_voidstar = malloc(sizeof(struct sockaddr_storage)));
> ...")
> 
> That seems to work.  But I'd bet this leaks memory as gamsock never
> frees this memory.
> 
> Q: Does it leak?  Or is there some gambit magic default?
> 
> # Part II, the crazy thing
> 
> If I got that right, than what I'd need to fix the leak was to attach a
> /will/ to the socket-address, which would free the storage and return
> ___NO_ERR.
> 
> Q: Correct?
> 
> If yes, is this a good idea?  I'd assume that allocating short lived
> objects from the Scheme heap should be much less expesive.  Isn't it?
> 
> 
> # Part III, how?
> 
> 1. How would I allocate a short lived object on the scheme heap?
> 2. Still have it properly tagges as foreign object for type checking.
>   (I.e., I know I could allocate a u8vector of the size I need.
>    But this is an u8vector for Scheme, which I don't want.)
> 
> Thanks
> 
> /Jörg
> 
> 
> _______________________________________________
> Gambit-list mailing list
> Gambit-list at iro.umontreal.ca
> https://mailman.iro.umontreal.ca/cgi-bin/mailman/listinfo/gambit-list





More information about the Gambit-list mailing list