记忆为ghci中的严格和/严格折叠而爆炸

art*_*lla 2 haskell memory-leaks ghci

如前所述(sum $ takeWhile(<10000000)[1 ..])会使用如此多的内存吗?以下就不会在炸毁内存ghci的:

foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]
Run Code Online (Sandbox Code Playgroud)

但是,如果我创建一个文件包含:

import Data.List

longList::[Int]
longList = [1 .. ]

result :: Int
result = foldl' (+) 0 $ takeWhile (< 10000000) longList

main = do
  print $ result
Run Code Online (Sandbox Code Playgroud)

并加载到ghci,然后在运行程序时,内存消耗爆炸.为什么这样,我该怎么做才能解决这个问题呢?我正在使用ghc 7.8.3.

[编辑]

如果我先编译,它似乎没有爆炸ghc Test.hs.但是,如果我删除所有.hi.o文件,并加载到ghci中通过ghci Test.hs那么内存确实炸毁.

Ørj*_*sen 7

我相信这是由于不同的处理标识的longList,当你:l在GHCI的文件,而不是当它被编译成.

当你:l ModuleName在ghci中,默认情况下所有模块中的顶级标识进入的范围,这样就可以有效地进行调试.对于您的示例,这包括longList.这意味着GHCi 在评估之后会保留内容longList,从而导致内存泄漏.我怀疑即使这样也是如此-fobjectcode,所以我不确定其他评论中讨论的行为实际上是一个错误.

相反,当您编译模块时,GHC使用模块导出列表来查找结果中公开的标识符.由于您没有明确的module声明,因此默认为(最后一段)

module Main (main) where
Run Code Online (Sandbox Code Playgroud)

这意味着在编译时,GHC可以注意到除了main未公开之外的所有标识符,并且longList仅使用一次.然后它可以保持其值,避免内存泄漏.

  • 现在我发现我必须使用`模块Main(main)where`和`ghci -fobject-code Test`(即你的答案和Sibi答案的混合).我认为当我写上面的评论时,我已经使用`-fobject-code`创建了一个bashrc别名,并没有意识到它是需要的. (2认同)