首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么嵌套的内存会永远泄漏?

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

Stack Overflow用户
提问于 2011-12-26 04:50:32
回答 1查看 652关注 0票数 16

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

代码语言:javascript
复制
import Control.Monad (forever)

main = do
    forever $ forever $ return ()

(用-O2,-O,-O0...,GHC7.0.3编译)我不明白为什么要泄漏-我在永远和我不太明白为什么这会泄漏内存之间使用了相当多这样的代码和异常处理程序。

我刚刚查看了Control.Monad的源代码,发现了以下内容:

代码语言:javascript
复制
{- 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:

代码语言:javascript
复制
forever a   = a >> forever a

而下面的定义工作起来没有问题:

代码语言:javascript
复制
forever a   = a >>= \_ -> forever a

>>操作符中有一些可疑的东西,因为我认为这段代码是等效的。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2011-12-26 05:16:27

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

票数 11
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8631503

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档