Freeing memory allocated with newCString
ffi, haskell, memory, memory-management
Solution
The issue is that `free` just indicates to the garbage collector that it can now collect the string. That doesn't actually force the garbage collector to run though -- it just indicates that the CString is now garbage. It is still up to the GC to decide when to run, based on heap pressure heuristics.
You can force a major collection by calling `performGC` straight after the call to `free`, which immediately reduces the memory to 5M or so.
E.g. this program:
import Foreign
import Foreign.C.String
import System.IO
import System.Mem
wait = do
putStr "Press enter" >> hFlush stdout
_ <- getLine
return ()
main = do
let s = concat $ replicate 1000000 ['0'..'9']
cs <- newCString s
cs `seq` wait -- (1)
free cs
performGC
wait -- (2)
Behaves as expected, with the following memory profile - the first red dot is the call to `performGC`, immediately deallocating the string. The program then hovers around 5M until terminated.
Problem
As library docs say `CString` created with `newCString` must be freed with `free` function. I have been expecting that when `CString` is created it would take some memory and when it is released with `free` memory usage would go down, but it didn't! Here is example code: ``` module Main where import Foreign import Foreign.C.String import System.IO wait = do putStr "Press enter" >> hFlush stdout _ <- getLine return () main = do let s = concat $ replicate 1000000 ['0'..'9'] cs <- newCString s cs `seq` wait -- (1) free cs wait -- (2) ``` When program stopped at (1), `htop` program showed that memory usage is somewhere around 410M - this is OK. I press enter and the program stops at line (2), but memory usage is still 410M despite `cs` has been `free`d! How is this possible? Similar program written in C behaves as it should. What am I missing here?