正如图书馆文档所说,使用CString
创建的newCString
必须使用free
函数释放。我一直期望在创建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 - 这没关系。我按回车键,程序在第(2)行停止,但内存使用率仍为410M,尽管cs
已free
d!
这怎么可能?用C编写的类似程序就像它应该的那样。我在这里缺少什么?
答案 0 :(得分:8)
问题是free
只是向垃圾收集器指示它现在可以收集字符串。这实际上并没有强制垃圾收集器运行 - 它只是表明CString现在是垃圾。根据堆压力启发式,仍然由GC决定何时运行。
您可以在调用performGC
之后直接调用free
来强制主要收藏集,这会立即将内存减少到5M左右。
E.g。这个程序:
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左右徘徊直到终止。