释放使用newCString分配的内存

时间:2012-05-09 09:09:02

标签: memory haskell memory-management ffi

正如图书馆文档所说,使用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,尽管csfree d!

这怎么可能?用C编写的类似程序就像它应该的那样。我在这里缺少什么?

1 个答案:

答案 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左右徘徊直到终止。

enter image description here