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