首先是问题 - 以下行为是逻辑上预期的,还是要为 GHC 报告的错误?
下面的代码将泄漏内存(在 上测试ghc-8.8.4
),因为ghc
似乎join point
在循环结束时添加并跳转到它,构建堆栈。
{-# OPTIONS_GHC -fno-full-laziness #-}
module Main where
import Control.Concurrent.Async (async,waitCatch)
import Data.IORef
import GHC.Conc
main :: IO ()
main = do
val <- newIORef 0 :: IO (IORef Int)
let loop1 = do
cval <- readIORef val
threadDelay 1
writeIORef val (cval + 1)
case cval > 100000000 of
True -> error "done"
False -> loop1
loop1 -- Deliberately, add this to cause space leak, but this statement is never executed because of case branching above
loop1Async <- async loop1
res <- waitCatch loop1Async
return ()
编译-O2 -rtsopts -threaded
和运行+RTS -s -hT -N
会因为堆栈的增长而显示空间泄漏。
查看核心输出,似乎泄漏是由于join
(我猜它是 a join point
)并且在循环结束时跳转到它会增加堆栈(如果我已经正确读取了核心)。删除最后一条语句loop1
可以修复泄漏。
ghc core
输出在这里。
更新:根据评论中的反馈,这似乎是合乎逻辑的行为,而不是ghc
. 因此,最好有一个解释堆栈增加的答案。这有助于我们了解这里发生了什么。ghc core
输出已在上面发布。