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

时间:2014-11-03 10:25:06

标签: haskell memory-management garbage-collection ghc ghci

简介

以下代码显示当使用runhaskell Haskell垃圾收集器释放内存时,不再使用a时。它会在释放变量a时导致核心转储 - 出于某种目的,检查行为 - a已将nullFunPtr作为终结器。

module Main where

import Foreign.Ptr 
import Foreign.ForeignPtr


main :: IO ()
main = do
    a <- newForeignPtr nullFunPtr nullPtr
    putStrLn "Hello World"

问题

在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

内存在退出时被释放,但对我来说已经太晚了。我正在扩展GHCi并将其用于其他目的,我需要提前释放内存 - 按需或尽可能快地发布内存。

我知道我可以调用finalizeForeignPtr,但我只是出于调试目的使用foreignPtr。如何在上一个示例中一般发布a

如果没有可能使用ghci提示,我也可以修改ghci代码。也许我可以通过modyfing ghci Interactive ContextDynFlags发布这个a?到目前为止,我的研究工作没有运气。

1 个答案:

答案 0 :(得分:9)

跟踪代码,我们发现该值存储在数据类型closure_env的字段PersistentLinkerState中,即ClosureEnv,即从名称到{{1}的映射}}秒。 HValue中的相关功能是

Linker.hs

虽然评论表明它应该删除阴影绑定,但它不会,至少不是你想要它的方式。

原因是,正如AndrewC正确写道:尽管两个变量都具有相同的源代码名称,但它们与编译器不同(它们附加了不同的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 } )。我们可以在上面的函数中添加一些跟踪后观察到这一点:

Unique

此时删除具有相同源名称的绑定应解决您的GC问题,但我不太了解编译器,以告诉其他什么会破坏。我建议你打开一张票,希望有人知道。

对绑定与价值的混淆

在评论中,似乎有一些关于绑定和值的混淆。请考虑以下代码:

*GHCiGC> a <- newForeignPtr nullFunPtr nullPtr
extendLinkEnv [a_azp]
*GHCiGC> a <- return ()
extendLinkEnv [a_aF0]
*GHCiGC> performGC
extendLinkEnv [it_aFL]

使用当前实现,堆将由`

组成
  • > a <- return something > b <- return somethingelse > a <- return (b+b) > b <- return anewthing
  • something
  • 引用somethingelse运算符和(+)
  • 的thunk
  • somethingelse

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

remdezx正确地期望GHCi会将引用放到anewthingsomething。反过来,这将允许运行时系统进行垃圾收集somethingelse(我们假设没有进一步的引用)。 GHCi仍然引用thunk,而thunk又引用something,所以这将被垃圾收集。

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