gpt4 book ai didi

haskell - 如何让 GHCI 释放内存

转载 作者:行者123 更新时间:2023-12-03 01:16:00 26 4
gpt4 key购买 nike

简介

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

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 Context 发布这个 aDynFlags ?到目前为止,我的研究还没有进展。

最佳答案

追踪代码我们发现该值存储在PersistentLinkerState数据类型的closure_env字段中,它是一个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 }

虽然注释表明它应该删除阴影绑定(bind),但它没有,至少没有按照您希望的方式删除。

原因是,正如AndrewC正确编写的:虽然两个变量具有相同的源代码名称,但它们对于编译器来说是不同的(它们附加了不同的Unique)。在向上面的函数添加一些跟踪后,我们可以观察到这一点:

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

此时删除具有相同源名称的绑定(bind)应该可以解决您的 GC 问题,但我不太了解编译器,无法判断还会破坏什么。我建议你开个票,希望有人知道。

绑定(bind)与值(value)的混淆

在评论中似乎对绑定(bind)和值有些困惑。考虑这段代码:

> a <- return something
> b <- return somethingelse
> a <- return (b+b)
> b <- return anewthing

在当前的实现中,堆将由`

组成
  • 某事
  • 其他东西
  • 引用 (+) 运算符和 somethingelse
  • 新事物

此外,解释器的环境引用了所有四个堆值,因此无法对任何内容进行 GC。

remdezx 正确地期望 GHCi 会删除对 somethingsomethingelse引用。反过来,这将允许运行时系统垃圾收集某些东西(我们假设没有进一步的引用)。 GHCi 仍然引用 thunk,而 thunk 又引用 somethingelse,因此这不会被垃圾收集。

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

关于haskell - 如何让 GHCI 释放内存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26712188/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com