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

时间:2011-12-25 20:50:32

标签: 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应该是“固定的”;不幸的是,嵌套永远会再次触发bug。有趣的是,这个永远的定义(借用Control.Monad)触发了错误:

forever a   = a >> forever a

虽然以下定义没有问题:

forever a   = a >>= \_ -> forever a

>>运算符中有一些可疑的内容,因为我将此代码视为等效。

1 个答案:

答案 0 :(得分:11)

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