首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >不断增长的堆栈大小和无意的循环语句-预期的行为?

不断增长的堆栈大小和无意的循环语句-预期的行为?
EN

Stack Overflow用户
提问于 2021-08-27 22:53:53
回答 1查看 67关注 0票数 0

第一个问题--行为低于预期是合乎逻辑的,还是应该向GHC报告一个bug?

下面的代码会泄漏内存(在ghc-8.8.4上测试),因为ghc似乎添加了join point,并在循环结束时跳转到它,从而构建了堆栈。

代码语言:javascript
复制
{-# 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 (我猜它是一个join point)和循环末尾的跳转导致堆栈增长(如果我没有读错核心的话)。删除loop1中的最后一条语句可以修复泄漏。

ghc core输出为here

更新:根据评论中的反馈,这似乎是符合逻辑的行为,而不是ghc中的错误。因此,有一个解释堆栈增加的答案是很好的。这有助于我们了解这里发生了什么。上面已经发布了ghc core输出。

EN

回答 1

Stack Overflow用户

发布于 2021-08-28 02:39:14

我当然希望这一行会导致堆栈空间的使用。对loop1的额外调用几乎是无关紧要的。

将测试常量更改为10,而不是更大的数字,并将return ()分支替换为print cval

比较使用和不使用"never executed“语句得到的输出。您可能会发现它的执行程度比您想象的要高。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/68960060

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档