我试图将Data.Binary.Put monad包装到另一个中,以便稍后我可以问它“将要写入多少字节”或“文件中当前位置是什么”等问题。但即使很琐碎的包装如:为什么包装Data.Binary.Put monad会造成内存泄漏?
data Writer1M a = Writer1M { write :: P.PutM a }
or
data Writer2M a = Writer2M { write :: (a, P.Put) }
创建一个巨大的空间泄漏和程序通常崩溃(占用4GB的RAM后)。以下是我试过到目前为止:
-- This works well and consumes almost no memory.
type Writer = P.Put
writer :: P.Put -> Writer
writer put = put
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut writer)
-- This one will cause memory leak.
data Writer1M a = Writer1M { write :: P.PutM a }
instance Monad Writer1M where
return a = Writer1M $ return a
ma >>= f = Writer1M $ (write ma) >>= \a -> write $ f a
type WriterM = Writer1M
type Writer = WriterM()
writer :: P.Put -> Writer
writer put = Writer1M $ put
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut $ write writer)
-- This one will crash as well with exactly the
-- same memory foot print as Writer1M
data Writer2M a = Writer2M { write :: (a, P.Put) }
instance Monad Writer2M where
return a = Writer2M $ (a, return())
ma >>= f = Writer2M $ (b, p >> p')
where (a,p) = write ma
(b,p') = write $ f a
type WriterM = Writer2M
type Writer = WriterM()
writer :: P.Put -> Writer
writer put = Writer2M $ ((), put)
writeToFile :: String -> Writer -> IO()
writeToFile path writer = BL.writeFile path (P.runPut $ snd $ write writer)
我是新来的Haskell,这是没有SENCE给我,但包装单子看起来很琐碎,所以我猜有是我失踪的事情。
感谢您的期待。
UPDATE: 下面是一个说明该问题的示例代码:http://hpaste.org/43400/why_wrapping_the_databinaryp
UPDATE2: 还有一个第二部分这个问题here。
你使用什么编译器标志? – 2011-01-28 14:36:27
当你问我用-O2试过(我以前没有用过),但记忆足迹没有改变。 – 2011-01-28 14:49:47