haskell - 内存在 ghci 中因严格求和/严格折叠而爆炸

标签 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,那么内存就会爆炸。

最佳答案

我认为这是由于在 GHCi 中 :l 文件时标识符 longList 的处理方式与编译时不同。

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

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

module Main (main) where

这意味着在编译时,GHC 可以注意到除 main 之外的所有标识符都没有暴露,并且 longList 只使用了一次。然后它可以放弃保持它的值(value),避免内存泄漏。

关于haskell - 内存在 ghci 中因严格求和/严格折叠而爆炸,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24838982/

相关文章:

haskell - 在 Haskell 中,如果 Maybe 是一个类型或一个联合类型,你怎么称呼 `Nothing` ?

c++ - 分配结构数组后内存被覆盖

haskell - 我怎么知道需要哪个 libstdc++ 双重转换?

haskell - 如何停止 GHCi 中的无限评估?

c - 在 C 中实现 MVar?

haskell - GHCJS-DOM 事件指导

c# - GC.Collect() 和 PerformanceCounter

haskell - GHCI 断点问题

arrays - Haskell 中的非整体数组

.net - 尽管所有堆中都有常量字节,有什么方法可以限制 Gen 0、1 和 2 的垃圾收集?这是内存泄漏的迹象吗?