这段代码会泄漏内存(非常快,如果你尝试它,准备好很快杀死它):
import Control.Monad (forever)
main = do
forever $ forever $ return ()
(用-O2,-O,-O0...,GHC7.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)触发了这个bug:
forever a = a >> forever a
而下面的定义工作起来没有问题:
forever a = a >>= \_ -> forever a
在>>
操作符中有一些可疑的东西,因为我认为这段代码是等效的。
发布于 2011-12-26 05:16:27
您正在查看的是最新版本的base
,这可能不是您正在使用的版本。base 4.3.1.0中的forever
不使用INLINABLE
。如果我使用GHC 7.2.2和base 4.4.1.0运行您的示例,我不会得到空间泄漏。
https://stackoverflow.com/questions/8631503
复制相似问题