Haskell freed memory allocated by C-runtime

I am learning how to use Haskell C FFI.

Suppose I call a C function that creates an object and then returns a pointer to that object. Can I free this memory from Haskell runtime with free? (I mean Haskell free not C free)

Consider the following code:

{-# LANGUAGE ForeignFunctionInterface #-}
module Main where
import Prelude hiding (exp)
import Foreign.Marshal.Alloc
import Foreign.Storable
import Foreign.C.Types
import Foreign.Ptr 
import Foreign.Marshal.Array

foreign import ccall "get_non_freed_array"  c_get_non_freed_array :: CInt -> IO (Ptr CInt) -- An array initialized

main :: IO()
main = do
  let numelements = 5
  ptr <-  c_get_non_freed_array  numelements
  w0  <-  peek $ advancePtr ptr 0 
  w1  <-  peek $ advancePtr ptr 1 
  w2  <-  peek $ advancePtr ptr 2 
  w3  <-  peek $ advancePtr ptr 3 
  w4  <-  peek $ advancePtr ptr 4 
  print [w0, w1, w2, w3, w4]
  return ()

The function get_non_freed_arrayI wrote in C99 is as follows

#include "test.h"
#include <stdlib.h>
// return a memory block that is not freed.
int* get_non_freed_array(int n)
{
  int* ptr = (int*) malloc(sizeof(int)*n);

  for(int i=0 ; i<n ; ++i){
          ptr[i] = i*i;
   }
  return ptr;
}

( test.hcontains only one line containing the function signature get_non_freed_arrayfor Haskell FFI to access it.)

, , , C-runtime, , C Haskell. , C, , , , Haskell get_non_freed_array, , .

, Haskell , , , C-, ptr.

, Haskell? C-, , destroy_array(int* ptr) test.c, Haskell?


:. , , , C-, Haskell.

+4
1

TL; DR: (, C malloc C free) alloca - ForeignPtr, .


A Ptr - . Addr# . : , , C-runtime, C.

, Haskell. C malloc, C free. Haskell free C, , Foreign.Marshal.Alloc.free Haskell.

, . GHC C-, . destroy_array: Lucky , :

foreign import ccall "stdlib.h free" c_free :: Ptr CInt -> IO ()

C , free . main :

main :: IO()
main = do
  let numelements = 5
  ptr <-  c_get_non_freed_array  numelements
  w0  <-  peek $ advancePtr ptr 0 
  w1  <-  peek $ advancePtr ptr 1 
  w2  <-  peek $ advancePtr ptr 2 
  w3  <-  peek $ advancePtr ptr 3 
  w4  <-  peek $ advancePtr ptr 4 
  print [w0, w1, w2, w3, w4]
  c_free ptr
  return ()

, , C. . ForeignPtr. Ptr newForeignPtr:

newForeignPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)

FinalizerPtr (type FinalizerPtr a = FunPtr (Ptr a -> IO ()) - . :

--                                    v
foreign import ccall unsafe "stdlib.h &free" c_free_ptr :: FinalizerPtr CInt
--                                    ^

:

makeArray :: Int -> ForeignPtr CInt
makeArray n = c_get_non_freed_array >>= newForeignPtr c_free_ptr

ForeignPtr, withForeignPtr:

main :: IO()
main = do
  let numelements = 5
  fptr <-  makeArray  numelements
  withForeignPtr fptr $ \ptr -> do
      w0  <-  peek $ advancePtr ptr 0 
      w1  <-  peek $ advancePtr ptr 1 
      w2  <-  peek $ advancePtr ptr 2 
      w3  <-  peek $ advancePtr ptr 3 
      w4  <-  peek $ advancePtr ptr 4 
      print [w0, w1, w2, w3, w4]
  return ()

Ptr ForeignPtr , . . alloca* , -, , , .

withArrayLen xs $ \n ptr -> do
   c_fast_sort n ptr
   peekArray n ptr

Foreign.Marshal.* .

: . , .

+1

Source: https://habr.com/ru/post/1674672/


All Articles