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

ond*_*dra 16 haskell memory-leaks

这段代码泄漏了内存(非常快,如果你尝试的话,准备很快杀死它):

import Control.Monad (forever)

main = do
    forever $ forever $ return ()
Run Code Online (Sandbox Code Playgroud)

(编译-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.
-}
Run Code Online (Sandbox Code Playgroud)

这个错误据说是"固定的"; 不幸的是,嵌套永远会再次触发bug.有趣的是,这个永远的定义(借用Control.Monad)触发了错误:

forever a   = a >> forever a
Run Code Online (Sandbox Code Playgroud)

虽然以下定义没有问题:

forever a   = a >>= \_ -> forever a
Run Code Online (Sandbox Code Playgroud)

>>运算符中有些东西可疑,因为我将此代码视为等效.

Joe*_*ams 11

您正在查看最新版本base,可能不是您正在使用的版本.将forever在基础4.3.1.0不使用INLINABLE.如果我用GHC 7.2.2和基础4.4.1.0运行你的例子,我不会得到空间泄漏.

  • 你真的不需要Haskell平台; 如果你安装GHC 7.2.2和cabal-install(参见[GHC 7.2的特殊说明](https://gist.github.com/1169332);注意:这适用于每个平台,而不仅仅是OS X)你可以`cabal install`您自己需要的任何包装.Haskell平台的价值仅来自预编译和打包. (2认同)