haskell - 为什么嵌套永远泄漏内存?

标签 haskell memory-leaks

此代码泄漏内存(非常快,如果您尝试它,请准备好尽快杀死它):

import Control.Monad (forever)

main = do
    forever $ forever $ return ()

(使用 -O2、-O、-O0...、ghc 7.0.3 编译)
我不明白为什么要泄漏-我在永远之间使用了很多带有异常处理程序的此类代码,我不太明白为什么这应该泄漏内存..

我刚刚查看了 Control.Monad 的源代码,发现了这个:
{- Note [Make forever INLINABLE]

If you say   x = forever a
you'll get   x = a >> a >> a >> a >> ... etc ...
and that can make a massive space leak (see Trac #5205)

In some monads, where (>>) is expensive, this might be the right
thing, but not in the IO monad.  We want to specialise 'forever' for
the IO monad, so that eta expansion happens and there's no space leak.
To achieve this we must make forever INLINABLE, so that it'll get
specialised at call sites.

Still delicate, though, because it depends on optimisation.  But there
really is a space/time tradeoff here, and only optimisation reveals
the "right" answer.
-}

这个bug据说是“固定的”;不幸的是,似乎嵌套永远再次触发了该错误。有趣的是,这个永远的定义(从 Control.Monad 借来的)触发了这个错误:
forever a   = a >> forever a

虽然以下定义可以正常工作:
forever a   = a >>= \_ -> forever a
>> 中有一些可疑的东西运算符,因为我希望这段代码是等效的。

最佳答案

您正在查看 base 的最新版本,这可能不是您使用的。 forever 在基础 4.3.1.0 中不使用 INLINABLE .如果我使用 GHC 7.2.2 和 base 4.4.1.0 运行您的示例,则不会出现空间泄漏。

关于haskell - 为什么嵌套永远泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8631503/

相关文章:

haskell - 如何将延续单子(monad)分解为左右伴随?

haskell - 在 Haskell 中将 IO 字符串写入标准输出

haskell - 元组声明进入无限循环

haskell - 如何使用两个映射遍历 Haskell 中的二元组?

android - 作为监听器的 Activity 和内存泄漏

java - Log4j2 - ServletContextListener 中的 ThreadLocal 内存泄漏

c++ - istream_iterator 内存泄漏

cocoa - windowScriptObject setValue :self forKey:? 中的 WebView 内存泄漏

c# - 为什么最后一个关闭的 MDI 子窗体没有被垃圾回收?

haskell - 使用无限列表管理内存使用