rem*_*ezx 23 garbage-collection haskell memory-management ghc ghci
介绍
以下代码显示使用runhaskellHaskell Garbage Collector时释放内存,何时a不再使用.它导致核心转储,同时释放变量a- 为了一个目的,检查行为 - a已经nullFunPtr作为终结器.
module Main where
import Foreign.Ptr
import Foreign.ForeignPtr
main :: IO ()
main = do
a <- newForeignPtr nullFunPtr nullPtr
putStrLn "Hello World"
Run Code Online (Sandbox Code Playgroud)
问题
在ghci中运行相同时,它不会释放内存.如何强制ghci释放不再使用的变量?
$ ghci
> import Foreign.Ptr
> import Foreign.ForeignPtr
> import System.Mem
> a <- newForeignPtr nullFunPtr nullPtr
> a <- return () -- rebinding variable a to show gc that I'm no longer using it
> performGC
> -- did not crash - GC didn't release memory
> ^D
Leaving GHCi.
[1] 4396 segmentation fault (core dumped) ghci
Run Code Online (Sandbox Code Playgroud)
内存在退出时被释放,但这对我来说太迟了.我正在扩展GHCi并将其用于其他目的,我需要尽早释放内存 - 按需或尽可能快地释放内存.
我知道我可以打电话finalizeForeignPtr,但我foreignPtr只是用于调试目的.a在上一个例子中我怎样才能发布?
如果没有可能用ghci提示做,我也可以修改ghci代码.也许我可以a通过modyfing ghci Interactive Context或DynFlags来释放它?到目前为止,我的研究工作没有运气.
通过我们发现该值被存储在字段中的代码跟踪closure_env的数据类型PersistentLinkerState,这是一个ClosureEnv,即,从名称到一个映射HValue秒.相关功能Linker.hs是
extendLinkEnv :: [(Name,HValue)] -> IO ()
-- Automatically discards shadowed bindings
extendLinkEnv new_bindings =
modifyPLS_ $ \pls ->
let new_closure_env = extendClosureEnv (closure_env pls) new_bindings
in return pls{ closure_env = new_closure_env }
Run Code Online (Sandbox Code Playgroud)
虽然注释表明它应该删除阴影绑定,但它不会,至少不是你想要它的方式.
原因是,正如AndrewC正确写道:尽管两个变量都具有相同的源代码名称,但它们与编译器不同(它们具有不同的Unique附加).我们可以在上面的函数中添加一些跟踪后观察到这一点:
*GHCiGC> a <- newForeignPtr nullFunPtr nullPtr
extendLinkEnv [a_azp]
*GHCiGC> a <- return ()
extendLinkEnv [a_aF0]
*GHCiGC> performGC
extendLinkEnv [it_aFL]
Run Code Online (Sandbox Code Playgroud)
此时删除具有相同源名称的绑定应该可以解决您的GC问题,但我不太清楚编译器是否足以告诉其他什么会破坏.我建议你打开一张票,希望有人知道.
对绑定与价值的混淆
在评论中,似乎有一些关于绑定和值的混淆.考虑以下代码:
> a <- return something
> b <- return somethingelse
> a <- return (b+b)
> b <- return anewthing
Run Code Online (Sandbox Code Playgroud)
使用当前实现,堆将包含`
somethingsomethingelse(+)运算符的thunksomethingelseanewthing.此外,解释器的环境引用了所有四个堆值,因此没有任何东西可以用于GC.
remdezx正确地期望GHCi会放弃对和的引用.反过来,这将允许运行时系统进行垃圾收集(我们假设没有进一步的引用).GHCi仍然引用thunk,而thunk反过来引用,所以这不会被垃圾收集.somethingsomethingelsesomethingsomethingelse
显然这个问题非常具体,所以这个答案也是如此:-)