2011-12-25 20 views
16

Este código pérdidas de memoria (muy rápido, estar preparado para matarlo pronto si lo intentas):¿Por qué anida para siempre la memoria?

import Control.Monad (forever) 

main = do 
    forever $ forever $ return() 

(Compilado con O2, = O, -O0 ..., GHC 7.0.3) No entiendo por qué debería tener esta fuga: estoy usando bastante código con manejador de excepciones entre los para siempre y no entiendo por qué se supone que esto pierde memoria ...

Acabo de buscar fuentes para Control.Monad y encontró esto:

{- 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. 
-} 

Este bug supuestamente es 'fijo'; desafortunadamente, parece que el anidado para siempre desencadena el error nuevamente. Curiosamente, esta definición de siempre (tomado de Control.Monad) provoca el error:

forever a = a >> forever a 

Mientras que la siguiente definición de trabajo sin problemas:

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

Hay algo sospechoso en el operador >>, como yo sería este código para ser equivalente.

Respuesta

11

Estabas mirando la última versión de base, que probablemente no es lo que estás usando. El forever en la base 4.3.1.0 no usa INLINABLE. Si ejecuto su ejemplo con GHC 7.2.2 y la base 4.4.1.0, no obtengo una fuga de espacio.

+0

Ok, esto parece estar solucionado en 7.2.2. Desafortunadamente, la plataforma haskell parece usar 7.0.4, y tengo 7.0.3 en mi Ubuntu :(Tendré que encontrar una manera de instalar versiones más nuevas. – ondra

+2

Realmente no necesita la plataforma Haskell, si instala GHC 7.2. 2 y cabal-install (consulte [instrucciones especiales para GHC 7.2 aquí] (https://gist.github.com/1169332); nota: esto funciona en todas las plataformas, no solo en OS X) puede "instalar cabal" cualquier paquete usted se necesita. El valor de la Plataforma Haskell solo proviene de ser precompilado y empaquetado. – ehird

Cuestiones relacionadas