[racket] Freeing FFI resources

From: Neil Toronto (neil.toronto at gmail.com)
Date: Mon Oct 11 19:42:52 EDT 2010

Eli Barzilay wrote:
> 5 hours ago, Neil Toronto wrote:
>> I'd be wary of the bytes/free example: I'd free the bytes ASAP instead 
>> of using a finalizer.
> 
> That shouldn't be a problem.

Not for correctness, no. How about for time or memory efficiency?

>> I confused the crap out of Racket's GC by keeping externally-managed
>> memory around that was pointed at by Racket-owned objects with
>> registered finalizers.
> 
> That should work fine.

Racket executed my programs correctly, yes. Efficiently? No.

>> (I made sure the external memory was properly atomic, like bytes
>> are.)
> 
> "Properly atomic" might be an indicationof the problem -- external
> memory is invisible to the racket GC, and there is no distinction
> between atomic blocks or whatever -- as far as racket knows, it's a
> pointer to something it doesn't care about.  So it might be that you
> were `malloc'ing memory yourself, and using `atomic' instead of `raw'
> (the latter gives you access to plain malloc(), which results in
> memory blocks that are GC-invisible).

That wasn't it.

I've had three reply drafts that spelled out the actual problem, but 
every one of them was too long and took too much work to make sure you'd 
understand the precise problem, motivation, etc. I had a good reason for 
trying what I did, I did it right, and the result was correct but 
memory-inefficient.

Imagine having a Racket-managed struct that contains a single C pointer 
to a large piece of unmanaged memory that was allocated by an external 
library, and that the struct has a finalizer that calls the deallocator. 
Now imagine having a lot of them at once.

My structs were a smidge more complicated, and Racket bloated in memory 
when I used them. Hence my general preference for copy-and-free over 
registering a finalizer.

Neil T


Posted on the users mailing list.