garbage collection and Ptr/ForeignPtr/StablePtr

Alastair Reid alastair at reid-consulting-uk.ltd.uk
Tue Sep 23 13:11:01 EDT 2003


On Monday 22 September 2003 12:10 pm, Bayley, Alistair wrote:
> Should I expect that Ptr memory allocated with malloc is garbage collected
> when no longer used by the Haskell runtime? The FFI spec doesn't say so
> explicitly (that I could see); 

C programs use pointers in many ways: pointers to static objects, pointers to 
stack-allocated objects, etc. as well as pointers to malloc-allocated 
objects.  These are all represented with a 'Ptr' in Haskell but only one of 
them should be freed.

Also, there are many ways to free a malloced object in C programs.  You might 
have to decrement a reference count, you might have to first free any objects 
it contains pointers to, you might call a library-specific free routine 
called 'xfree', you might call a type-specific freeing routine or you might 
just call free.

For all these reasons, Haskell's garbage collector cannot just call 'free' for 
you.

> AFAICT this is how the pointer types behave:
>   Ptr : freed when no longer used/referenced

No.

If it needs freed, you have to explicitly deallocate this by calling an 
appropriate routine.
This effectively means that you use Ptr for things accessed inside the IO 
monad.

>   ForeignPtr : like Ptr, but will also run a finaliser when freed

Yes.  The finalizer is (a pointer to) any C function you like.
ForeignPtr is especially useful for datatypes accessed outside the IO monad.  
e.g., if you wanted to use a complex number library, you might use ForeignPtr 
for the freeing function.
ForeignPtr is also useful even if you are in the IO monad when you don't have 
a simple access pattern like 'allocate; use; free;'.

Note that the ffi libraries provide functions called 'malloc' and 'free' and a 
finalizer called 'finalizerFree'.  It is tempting to think that these are the 
C library 'malloc'/'free' and (a pointer to) 'free'.  This is not necessarily 
so and you must take care that:

- you only use MarshallAlloc.free and MarshallAlloc.finalizerFree with
  memory allocated using MarshallAlloc.malloc

- you only use libc's 'free' with memory allocated using libc's 'malloc'.

>   StablePtr : not freed or collected

Yes.  StablePtrs are in a different category because they are pointers from C 
into Haskell (in contrast, Ptrs and ForeignPtrs are pointers from Haskell 
into C).  Since C doesn't have garbage collection, it is up to your C code to 
explicitly call 'freeStablePtr'. 

> (I haven't tested this; I've only read the FFI spec.)

I had a quick reread of sections 5.4 and 5.5 and I think your confusion is 
understandable.  It doesn't say anything about deallocation so you might 
plausibly guess that the story is the same as for Int8 (say) which also says 
nothing about deallocation.  ForeignPtrs are contrasted with Ptrs but only in 
whether or not they have finalizers.

I think the ffi spec has now been finalized so it's too late to fix this but 
perhaps the next revision could include the following wording (inserted after 
the first sentence of section 5.4).

  Objects of type 'Ptr a' and 'FunPtr a' are garbage collected
  in the normal way but the objects they _point to_ are not garbage
  collected.   If the objects pointed to require deallocation, this
  must be done by explicitly calling an appropriate function such as
  the C library function 'free'.

I have put some of the above in my FFI guide at:

  http://www.reid-consulting-uk.ltd.uk/docs/ffi.html

--
Alastair Reid     www.haskell-consulting.com





More information about the Haskell-Cafe mailing list