Освобождение памяти, выделенной с помощью 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 была freed!
как это возможно? Аналогичная программа, написанная на 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 до завершения.
