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

时间:2014-07-19 09:47:07

标签: haskell memory-leaks ghci

正如Why does (sum $ takeWhile (<10000000) [1..]) use so much memory?中提到的,以下 ghci 中炸毁内存:

foldl' (+) 0 $ takeWhile (< 10000000) [1 .. ]

但是,如果我创建一个包含以下内容的文件:

import Data.List

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

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

main = do
  print $ result

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

[编辑]

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

2 个答案:

答案 0 :(得分:7)

我认为这是因为当您在GHCi中longList文件时对标识符:l的处理方式不同,而不是在编译时。{/ p>

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

当您编译模块时,GHC使用模块导出列表找出结果中公开的标识符。由于您没有明确的module声明,因此默认为(last paragraph

module Main (main) where

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

答案 1 :(得分:2)

请参阅note on GHCI

部分
  

如果您在GHCi中运行代码时注意到空间泄漏,   请注意,解释的代码与编译的行为不同   代码:即使使用seq

     

考虑按如下方式启动ghci:

     

$ ghci -fobject-code