
If a C function returns a (void*), let's say: data MyObj = MyObj foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO (Ptr MyObj) ptr <- newMyObject should I free the ptr afterwards or not? If I have another imported C function: foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO () Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times? Any hints is greatly appreciated! Regards, .paul.

On Thu, 3 Jul 2003 11:34:08 +0800 paul@theV.net wrote:
If a C function returns a (void*), let's say:
data MyObj = MyObj
foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO (Ptr MyObj)
ptr <- newMyObject
should I free the ptr afterwards or not?
Assuming that it should be freed even in C and nothing else is managing it then I believe the answer is yes. You can use a finalizer to do it.
If I have another imported C function:
foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO ()
Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times?
What other pointer would it pass?

On Thu, Jul 03, 2003 at 01:40:46AM -0400, Derek Elkins wrote:
On Thu, 3 Jul 2003 11:34:08 +0800 paul@theV.net wrote:
If a C function returns a (void*), let's say:
data MyObj = MyObj
foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO (Ptr MyObj)
ptr <- newMyObject
should I free the ptr afterwards or not?
Assuming that it should be freed even in C and nothing else is managing it then I believe the answer is yes. You can use a finalizer to do it.
The wierd thing is, I cannot use the the function Foreign.Marshal.Alloc.free to free the ptr. I must use my own C function to do a simple free() call.
If I have another imported C function:
foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO ()
Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times?
What other pointer would it pass?
The same Haskell ptr. I wonder if they'll ever change after creation. My question is, if Ptr is equivalent to a raw void* pointer in C, and pointers created in foreign language (which is later passed to Haskell as Ptr) has to be freed in the foreign language, then can I safely assume that Ptr isn't affected by Haskell's GC cycle? And what the real difference between Ptr and StablePtr? Regards, .paul.

On Thu, 3 Jul 2003 15:04:26 +0800 paul@theV.net wrote:
On Thu, Jul 03, 2003 at 01:40:46AM -0400, Derek Elkins wrote:
On Thu, 3 Jul 2003 11:34:08 +0800 paul@theV.net wrote:
If a C function returns a (void*), let's say:
data MyObj = MyObj
foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO(Ptr MyObj)
ptr <- newMyObject
should I free the ptr afterwards or not?
Assuming that it should be freed even in C and nothing else is managing it then I believe the answer is yes. You can use a finalizer to do it.
The wierd thing is, I cannot use the the function Foreign.Marshal.Alloc.free to free the ptr. I must use my own C function to do a simple free() call.
You didn't allocate it with the Foreign library, why would you expect to free it with it? Actually, I'm kind of surprised it doesn't work, nevertheless I don't believe that the intent of the Alloc module is to free memory allocated by a foreign language, or allocate memory that will be freed by a foreign language. If you need to create/destroy a foreign value in Haskell, you typically provide both a creation and destruction function.
If I have another imported C function:
foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO ()
Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times?
What other pointer would it pass?
The same Haskell ptr. I wonder if they'll ever change after creation.
My question is, if Ptr is equivalent to a raw void* pointer in C, and pointers created in foreign language (which is later passed to Haskell as Ptr) has to be freed in the foreign language, then can I safely assume that Ptr isn't affected by Haskell's GC cycle? And what the real difference between Ptr and StablePtr?
The GC won't free the memory pointed at by the void * unless you attach a finalizer, in which case you obviously shouldn't be freeing it in the foreign code. The Ptr you get will be freed by Haskell's GC if it becomes unreferenced, but that won't affect what it points at. StablePtr's are for pointing at -Haskell- values.

paul@theV.net wrote:
The wierd thing is, I cannot use the the function Foreign.Marshal.Alloc.free to free the ptr. I must use my own C function to do a simple free() call.
Derek Elkins wrote:
You didn't allocate it with the Foreign library, why would you expect to free it with it? Actually, I'm kind of surprised it doesn't work, nevertheless I don't believe that the intent of the Alloc module is to free memory allocated by a foreign language, or allocate memory that will be freed by a foreign language. [...]
Foreign.Marshal.Alloc almost certainly uses either the allocator that is native to the language used to implement the Haskell runtime system. This is usually C so using the C 'free' function will often work but if your Haskell code were translated to Java instead, it would probably be allocated by a Java library and should be freed by the same Java library. Or Foreign.Marshal.Alloc might be optimized by exploiting the Haskell garbage collector in some way and so the memory has to be released in a way that informs the Haskell GC. In general (not just in Haskell's FFI), any time you allocate memory from a given memory pool or library, you should free it into the same memory pool/ library. (We tend not to be aware of this rule because most programs have just one allocator.) We could have avoided this problem by defining Foreign.Marshal.Alloc as a frontend for malloc/free. We didn't do so mostly because Foreign.Marshal.Alloc is intended to be language independent (i.e., your code should still work if interfacing to Java or if your Haskell code is compiled to/ interpreted by a Java program) and, in small part, because malloc/free implementations are so damn inefficient. -- Alastair Reid

Thank you for the explanation! So am I right to draw a picture like this? --------- --------- | Haskell | | Foreign | | Ptr |----->| Data | | Block | | Block | --------- --------- 1. If I allocate the data block in a foreign language and returns the pointer as Ptr through FFI, I have to free it in the foreign language after use. 2. If I allocate the data block through Marshal.Alloc, then I need to use Haskell free to deallocate it. (why the difference? GHC not using the default malloc/free in C lib?) 3. If the Haskell Ptr is no longer in use, the Haskell GC will collect it, regardless of whether it has a dangling pointer to Foreign Data Block. I only hope the Ptr part of FFI documentation can include some of the malloc/free guidelines, otherwise it is quite confusing for beginners. Regards, .paul. On Thu, Jul 03, 2003 at 03:49:21AM -0400, Derek Elkins wrote:
On Thu, 3 Jul 2003 15:04:26 +0800 paul@theV.net wrote:
On Thu, Jul 03, 2003 at 01:40:46AM -0400, Derek Elkins wrote:
On Thu, 3 Jul 2003 11:34:08 +0800 paul@theV.net wrote:
If a C function returns a (void*), let's say:
data MyObj = MyObj
foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO(Ptr MyObj)
ptr <- newMyObject
should I free the ptr afterwards or not?
Assuming that it should be freed even in C and nothing else is managing it then I believe the answer is yes. You can use a finalizer to do it.
The wierd thing is, I cannot use the the function Foreign.Marshal.Alloc.free to free the ptr. I must use my own C function to do a simple free() call.
You didn't allocate it with the Foreign library, why would you expect to free it with it? Actually, I'm kind of surprised it doesn't work, nevertheless I don't believe that the intent of the Alloc module is to free memory allocated by a foreign language, or allocate memory that will be freed by a foreign language. If you need to create/destroy a foreign value in Haskell, you typically provide both a creation and destruction function.
If I have another imported C function:
foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO ()
Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times?
What other pointer would it pass?
The same Haskell ptr. I wonder if they'll ever change after creation.
My question is, if Ptr is equivalent to a raw void* pointer in C, and pointers created in foreign language (which is later passed to Haskell as Ptr) has to be freed in the foreign language, then can I safely assume that Ptr isn't affected by Haskell's GC cycle? And what the real difference between Ptr and StablePtr?
The GC won't free the memory pointed at by the void * unless you attach a finalizer, in which case you obviously shouldn't be freeing it in the foreign code. The Ptr you get will be freed by Haskell's GC if it becomes unreferenced, but that won't affect what it points at. StablePtr's are for pointing at -Haskell- values.
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

paul@theV.net wrote:
So am I right to draw a picture like this? [...]
Basically, yes. Or from the Haskell implementation's view: "I don't have a clue what a Ptr really is, but it fits in C's void*."
[ 1. & 2. ]
The requirement for matching allocators and deallocators is not much different from the situation in e.g. C++: You can't "free" an object constructed via "new", you can't simply "delete" an array allocated with "new[]", etc.
3. If the Haskell Ptr is no longer in use, the Haskell GC will collect it, regardless of whether it has a dangling pointer to Foreign Data Block.
It is by no means clear if the pointer is "dangling", even if Haskell knew that a Ptr is really a pointer. Other C pointers or Haskell Ptrs could still reference the data. What the best approach is, depends on your problem: a) The C part does more than a simple malloc/free in its (de-)allocation functions, but the lifetime of the object is restricted. In this case, a "withNewFoo" Haskell action is often a good approach, e.g.: withNewFoo :: (Ptr a -> IO b) -> IO b withNewFoo = bracket c_alloc c_dealloc foreign import ccall unsafe "c_alloc" c_alloc :: IO (Ptr a) foreign import ccall unsafe "c_dealloc" c_dealloc :: Ptr a -> IO () b) Same as a), but the lifetime of the C object should be under control of the Haskell GC. In this case, you can use a ForeignPtr, which is basically a Ptr with attached finalizers. c) If the C part simply needs a buffer for some time, there are quite a few possibilities, depending on the required lifetime and ownership of the buffer: * explicit control via Foreign.Marshal.Alloc.malloc and Foreign.Marshal.Alloc.free * pooled allocation ("all or nothing") via Foreign.Marshal.Pool * Foreign.ForeignPtr.mallocForeignPtr* puts the buffer under control of Haskell's GC * explicitly delimited lifetime via Foreign.Marshal.Alloc.alloca
I only hope the Ptr part of FFI documentation can include some of the malloc/free guidelines, otherwise it is quite confusing for beginners.
The FFI spec is, well, a spec and not intended as a tutorial, but Alastair has written a guide to the FFI: http://www.reid-consulting-uk.ltd.uk/docs/ffi.html Cheers, S.

paul@theV.net wrote:
If a C function returns a (void*), let's say:
data MyObj = MyObj
foreign import ccall "static myobj_ffi.h new_obj" newMyObject :: IO (Ptr MyObj)
ptr <- newMyObject
should I free the ptr afterwards or not?
There's no single right answer to this - it all depends on the function. Here's three functions which return very different kinds of pointer. (They're somewhat bogus in other ways but are representative of real, useful functions.) Statically allocated - do not free T* newMyObject(void) { static T x; return &x; } Allocated with malloc - use free to release it T* newMyObject(void) { return (T*)malloc(sizeof T); } Reference counted - do not free T* newMyObject(void) { T* x = malloc(sizeof T); x->ref_count=1; return x; } There's several further variants like allocating from a separate memory pool. Basically, you have to carefully read the documentation of every function to find out how to release objects. Since documentation is often poor, you might also study the implementation or uses and you should get in the habit of always checking error codes (even on functions like printf which most C programmers have never checked in their life) because it will help find those cases where the documentation is wrong or incomplete.
If I have another imported C function:
foreign import ccall "static myobj_ffi.h print_obj" printMyObject :: Ptr MyObj -> IO ()
Can I safely assume the C function print_obj(void *) always get the same pointer even if I call (printMyObject ptr) multiple times?
If you have: do printMyObject ptr ... printMyObject ptr ... printMyObject ptr Then all three uses see the same pointer no matter what happens between the calls (assuming you dont use 'let ptr = ...' in the dots, of course). To put it another way, anything of type 'Ptr a' is an abstract type as far as Haskell is concerned. It is just a 32-bit object (or 64 or whatever) which Haskell doesn't directly understand. All it can do with such a value is copy it, pass it to/from functions, store it, etc. It certainly isn't going to try to treat it as a garbage collection root, or consider moving the object it points at. -- Alastair Reid
participants (4)
-
Alastair Reid
-
Derek Elkins
-
paul@theV.net
-
Sven Panne