memory - 为什么包装 Data.Binary.Put monad 会造成内存泄漏?

标签 memory haskell memory-leaks binary memory-management

我正在尝试将 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 的新手,这对我来说毫无意义,但包装器 monad 似乎非常微不足道,所以我猜我缺少一些明显的东西。

感谢收看。

更新: 下面是演示问题的示例代码:http://hpaste.org/43400/why_wrapping_the_databinaryp

更新2: 这个问题还有第二部分here .

最佳答案

摸索了一下,我发现问题似乎是使用二进制的(>>=)来实现(>>)。 Writer1M monad 实现的以下添加解决了该问题:

  m >> k = Writer1M $ write m >> write k

而这个版本仍然会泄漏内存:

  m >> k = Writer1M $ write m >>= const (write k)

binary's source , (>>) 似乎明确地丢弃了第一个 monad 的结果。不过,不确定这究竟是如何防止泄漏的。我最好的理论是,否则 GHC 会保留 PairS 对象,并且“a”引用会泄漏,因为它永远不会被查看。

关于memory - 为什么包装 Data.Binary.Put monad 会造成内存泄漏?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4828902/

相关文章:

c - C的智能指针/安全内存管理?

iOS 核心数据怎么会泄露?

java - 运行时查看java堆内容

haskell - 修改 monad 状态

ios - 实例化新 View Controller 时从内存中删除 View Controller

c++ - 追踪 WinSock MFC 应用程序中句柄泄漏的来源

android.view.ViewRootimpl$RunQueue$HandlerAction 防止 Dialog 被垃圾回收

ios - Swift:当我转到另一个 View Controller 时,内存未清除,收到内存警告

performance - 使用toList不好吗?

haskell - 如何在 Haskell 中使用 hedis 通过 Unix 域套接字连接到 redis 服务器?