Освобождение памяти, выделенной с помощью newCString
как говорят библиотечные документы CString
создано с помощью newCString
должен быть освобожден с . Я ожидал этого, когда CString
создается, это займет некоторую память, и когда она будет выпущена с free
использование памяти снизится, но это не так! Вот пример кода:
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)
когда программа остановилась на (1), htop
программа показала, что использование памяти где - то около 410M-это нормально. Я нажимаю enter, и программа останавливается на строке (2) , но использование памяти все еще Несмотря на 410 м cs
была free
d!
как это возможно? Аналогичная программа, написанная на C ведет себя как надо. Я что-то упускаю?
1 ответов
проблема в том, что free
просто указывает сборщику мусора, что теперь он может собирать строку. Это на самом деле не заставляет сборщик мусора работать, хотя-это просто указывает на то, что CString теперь мусор. Это все еще до GC, чтобы решить, когда запускать, на основе эвристики давления кучи.
вы можете силу основная коллекция по телефону performGC
сразу после звонка free
, которое немедленно уменьшает память до 5M или так.
Е. Г. в этой программе:
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)
ведет себя так, как ожидалось, со следующим профилем памяти - первая красная точка-это вызов performGC
, немедленно освобождая строку. Затем программа зависает вокруг 5M до завершения.