2011-12-25 14 views
16

このコードは(あなたがそれをしようとした場合、すぐにそれを殺すために準備され、非常に高速な)メモリをリーク:永久にメモリがネストされるのはなぜですか?

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 

>>オペレータで怪しい何かが私のように、ありますこのコードは同等になります。

答えて

11

baseの最新バージョンを確認していましたが、これはおそらく使用していないものです。ベース4.3.1.0のforeverINLINABLEを使用していません。私がGHC 7.2.2と4.4.1.0を使ってあなたの例を実行した場合、私はスペースリークを取得しません。

+0

これは7.2.2で修正されているようです。 Unfortunatelly haskellプラットフォームは7.0.4を使用しているようですが、私はUbuntuに7.0.3を持っています:(新しいバージョンをインストールする方法を見つけなければならないでしょう) – ondra

+2

GHC 7.2をインストールする場合、Haskell Platformは本当に必要ありません。 2とcabal-install([GHC 7.2の特別な手順はこちら](https://gist.github.com/1169332)を参照)、これはOS Xだけでなくすべてのプラットフォームで動作します。 Haskell Platformの価値は、あらかじめコンパイルされパッケージ化されているだけです。 – ehird

関連する問題