我怎样才能制作GHCI释放内存

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 ContextDynFlags来释放它?到目前为止,我的研究工作没有运气.

Joa*_*ner 9

通过我们发现该值被存储在字段中的代码跟踪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)

使用当前实现,堆将包含`

  • something
  • somethingelse
  • 一个引用(+)运算符的thunksomethingelse
  • anewthing.

此外,解释器的环境引用了所有四个堆值,因此没有任何东西可以用于GC.

remdezx正确地期望GHCi会放弃对和的引用.反过来,这将允许运行时系统进行垃圾收集(我们假设没有进一步的引用).GHCi仍然引用thunk,而thunk反过来引用,所以这不会被垃圾收集.somethingsomethingelsesomethingsomethingelse

显然这个问题非常具体,所以这个答案也是如此:-)

  • 绑定可以被遮蔽但仍然间接引用:`a < - return 1; f < - return(const a); a < - return(); print $ f undefined`. (2认同)
  • @Will Ness:不能再引用绑定了.当然''value''可以,但它可以通过闭包安全地引用,不需要"命名事物的环境"来保持它! (2认同)