We have four alternatives:
(1) We leave everything as it is. If you want malloc-type storage that you can free in a finaliser, you need to write your own interface to C's malloc() and free().
I think this approach misses the reason we provide MarshalAlloc in the first place.
(2) We commit to using C's storage manager in Haskell's malloc routines. Then, C's free() can be used to free storage allocated with Haskell's malloc routines. (Whether we already provide a foreign import declaration to access &free from Haskell or leave that to the application is a minor detail.)
It seems tidier not to do this. [Actually, I'd be tempted to strengthen the 'this is not C' feel of the library by renaming malloc/free, dropping realloc, making the size an explicit arguwent to free, etc. But any benefit from doing this would be small so I'll resist this temptation.]
(3) We provide a value
finalizerFree :: FunPtr (Ptr a -> IO ())
that frees storage allocated with Haskell's malloc routines without any guarantee that this coincides with C's free().
I think this is the best bet. (And it happens to be what Ross has just implemented for Hugs.)
(4) We add to the C land interface of the FFI a function
void hs_free (void *);
that behaves like MarshalAlloc.free, but can be called from a finalizer. (One can import this with &hs_free.)
This seems reasonable too. Kinda feels as though we'll end up doing this eventually if we don't do it now.
(Although, (4) suggests to also provide hs_malloc() and hs_realloc().)
Again, I suspect we'd end up doing these eventually if we don't do them now. -- Alastair